将所有键合并到 JavaScript 中具有相同 Id 的单个对象

Merge all keys into single object with the same Id in JavaScript

我有一组类似的对象。

var orderResults = [{
    id: '1',
    name: 'Maya Mahardhani',
    payment_amount : 100,
    sku: 'ST001802027',
    seq: '1'
},
{
    id: '1',
    name: 'Maya Mahardhani',
    payment_amount : 50,
    sku: 'ST000703044',
    seq: '2'
},
{
    id: '2',
    name: 'Tara Debu Batara',
    payment_amount : 100,
    sku: 'ST005101001',
    seq: '1'
},
{
    id: '3',
    name: 'Nikita Gigir',
    payment_amount : 100,
    sku: 'ST004403030',
    seq: '1'
}]

但我正在尝试通过以下方式提取数据。

[{
    id: '1',
    name: 'Maya Mahardhani',
    total_amount : 150,
    sku_1: 'ST001802027',
    sku_2: 'ST000703044',
},
{
    id: '2',
    name: 'Tara Debu Batara',
    total_amount : 100,
    sku_1: 'ST005101001'
},
{
    id: '3',
    name: 'Nikita Gigir',
    total_amount : 100,
    sku_1: 'ST004403030'
}]

我尝试使用 JavaScript 的 reduce 函数。但是它会用旧的覆盖 prev 键。我的代码片段就是这样。我想我更接近解决。但仍在寻求帮助

orderResults.reduce((res, obj) => {
    res[obj.id] = { 
        total_amount : (obj.id in res ? res[obj.id].total_amount : 0)  + obj.payment_amount,
        name : obj.name,
    }

    res[obj.id]['sku' + obj.seq]= obj.sku
    return res;
},[])

谢谢

我认为这会完成您想要做的事情:

orderResults.reduce((res, obj, i) => {
    const existingIdx = res.findIndex(r => r.id === obj.id)
    if (existingIdx > -1) {
      res[existingIdx] = { 
        ...res[existingIdx],
        total_amount : res[existingIdx].total_amount ? res[existingIdx].total_amount + obj.payment_amount : res[existingIdx].payment_amount + obj.payment_amount,
        name : obj.name,
        ['sku_' + obj.seq]: obj.sku
      }
    } else {
      res.push({
        id: obj.id,
        name: obj.name,
        total_amount: obj.payment_amount,
        ['sku_' + obj.seq]: obj.sku
      })
    }

    return res;
},[])

注意此行将保留原始对象并覆盖之后定义的任何重复键:

...res[existingIdx],

此外,当您的代码运行此行时:

res[obj.id] = {

它正在数组中设置一个特定的索引,我认为你不想这样做。您想要推送(如果尚未添加对象 ID),或者在创建具有相同 ID 的对象时覆盖原始插入点处的现有对象。

不要每次都创建一个新对象。

const result = Object.values(orderResults.reduce((res, obj) => {
    res[obj.id] = res[obj.id] ||
    {   
        id: obj.id,
        total_amount : 0,
        name : obj.name,
    };
    res[obj.id].total_amount += obj.total_amount;
    res[obj.id]['sku' + obj.seq] = obj.sku;
    return res;
},[]))
[{
    id: '1',
    name: 'Maya Mahardhani',
    payment_amount: 100,
    sku: 'ST001802027',
    seq: '1'
},
{
    id: '1',
    name: 'Maya Mahardhani',
    payment_amount: 50,
    sku: 'ST000703044',
    seq: '2'
},
{
    id: '2',
    name: 'Tara Debu Batara',
    payment_amount: 100,
    sku: 'ST005101001',
    seq: '1'
},
{
    id: '3',
    name: 'Nikita Gigir',
    payment_amount: 100,
    sku: 'ST004403030',
    seq: '1'
}].reduce((acc, current) => {
    const { id, name, payment_amount, sku, seq } = current;
    const previousRecord = acc[id];
    if (typeof previousRecord === 'object') {
        return {
            ...acc,
            [id]: {
                ...previousRecord,
                [`sku_${seq}`]: sku,
                total_amount: previousRecord.total_amount + payment_amount
            }
        }
    } else {

        return {
            ...acc,
            [id]: {
                id,
                name,
                [`sku_${seq}`]: sku,
                total_amount: payment_amount
            }
        }
    }
}, {}) // returns an Object; use Object.values to convert to a list