合并同一数组的 2 个对象,并对每个对象内的数组中的公共值求和

Merge 2 objects of same array and total the common values within the array inside each object

我尝试调查它,但找不到适合我的场景的具体用例。我相信这很简单,但我坚持了好几天。任何帮助将不胜感激

const stores = [
{
  id: "61f27aeb766e4b2924532f98",
  xName: 'SaurabhTest2',
  merchantIDs: [ "61f27bca766e4b2924532fb3" ],
  totalMerAcc: 1,
  oneTimeData: 100
},
{
  id: "61f2769b766e4b2924532f1f",
  xName: 'SaurabhTest',
  merchantIDs: [ "61f2788e766e4b2924532f54", "61f277b8766e4b2924532f31" ],
  totalMerAcc: 2,
  oneTimeData: 100
},
{
  id: "61f2769b766e4b2924532f1f",
  xName: 'SaurabhTest',
  merchantIDs: [ "61f277b8766e4b2924532f31" ],
  totalMerAcc: 1,
  oneTimeData: 100
}]

期望的输出:

[
{
  id: "61f27aeb766e4b2924532f98",
  xName: 'SaurabhTest2',
  merchantIDs: [ "61f27bca766e4b2924532fb3" ],
  totalMerAcc: 1,
  oneTimeData: 100
},
{
  id: "61f2769b766e4b2924532f1f",
  xName: 'SaurabhTest',
  merchantIDs: [ "61f2788e766e4b2924532f54", "61f277b8766e4b2924532f31" ],
  totalMerAcc: 2,
  oneTimeData: 100
}]

首先应根据“id”合并商店,然后还要检查两次合并之间是否已存在 merchantsID(此处可能有超过 2 个相同的 storeID,因此对象更多),并将所有不同的商店 ID 包含在一个对象中的 merchantID,然后将其合计到“totalMerAcc”中,以及 return 类似于上面的内容。

这里是我写的代码:

function mergeRecurrentsStores(businessStores) {
const result = businessStores.map((item) => {
    return [
        item[0],
        ...item[1]
            .reduce((accumulator, currentStore) => {
                const key = currentStore.id.toString();
                const innerItem =
                    accumulator.get(key) ||
                    Object.assign({}, currentStore, {
                        xName: currentStore.xName,
                        merchantIDs: currentStore.merchantIDs,
                        totalMerAcc: 0,
                        oneTimeData: currentStore.oneTimeData,
                    });
                if(innerItem.merchantIDs.some(i => i.includes(currentStore.merchantIDs)) {
                    
                }
                innerItem.totalMerAcc += currentStore.totalMerAcc;
                return accumulator.set(key, innerItem);
            }, new Map())
            .values(),
    ];
});
return result;}

示例结构在我正在减少的项目[1] 中。您可以忽略 item[0] 的情况。这只是管道中的下一件事。

欢迎任何帮助。

数组的map实现了一个映射操作。映射操作产生 1:1 结果,每个输入项对应一个结果项。但是您不希望那样,所以 map 不是正确的工具。

如果您使用预定义的、可重用的 reducer 函数进行函数式编程,reduce 可能是正确的工具,但如果您不是(而且您似乎不是,您的 reducer 是内联的) ,它只是一个 over-complicated 循环。相反,让我们做一个简单的循环。

const byId = new Map();
for (const store of stores) {
    let previous = byId.get(store.id);
    if (!previous) {
        // New one
        byId.set(store.id, store);
    } else {
        // Merge with previous
        // NOTE: If you don't want to modify the object in place, change
        // `const previous` above to `let previous` and uncomment this:
        /*
        previous = {...previous, merchantIDs: [...previous.merchantIDs]};
        byId.set(previous.id, previous);
        */
        for (const merchantID of store.merchantIDs) {
            if (!previous.merchantIDs.includes(merchantID)) {
                previous.merchantIDs.push(merchantID);
            }
        }
        previous.totalMerAcc = previous.merchantIDs.length; // It seems unnecessary to have `totalMerAcc`
    }
}

const result = [...byId.values()];

实例:

const stores = [
    {
        id: "61f27aeb766e4b2924532f98",
        xName: 'SaurabhTest2',
        merchantIDs: ["61f27bca766e4b2924532fb3"],
        totalMerAcc: 1,
        oneTimeData: 100
    },
    {
        id: "61f2769b766e4b2924532f1f",
        xName: 'SaurabhTest',
        merchantIDs: ["61f2788e766e4b2924532f54", "61f277b8766e4b2924532f31"],
        totalMerAcc: 2,
        oneTimeData: 100
    },
    {
        id: "61f2769b766e4b2924532f1f",
        xName: 'SaurabhTest',
        merchantIDs: ["61f277b8766e4b2924532f31"],
        totalMerAcc: 1,
        oneTimeData: 100
    }
];

const byId = new Map();
for (const store of stores) {
    const previous = byId.get(store.id);
    if (!previous) {
        // New one
        byId.set(store.id, store);
    } else {
        // Merge with previous
        // NOTE: If you don't want to modify the object in place, change
        // `const previous` above to `let previous` and uncomment this:
        /*
        previous = {...previous, merchantIDs: [...previous.merchantIDs]};
        byId.set(previous.id, previous);
        */
        for (const merchantID of store.merchantIDs) {
            if (!previous.merchantIDs.includes(merchantID)) {
                previous.merchantIDs.push(merchantID);
            }
        }
        previous.totalMerAcc = previous.merchantIDs.length; // It seems unnecessary to have `totalMerAcc`
    }
}

const result = [...byId.values()];
console.log(JSON.stringify(result, null, 4));
.as-console-wrapper {
    max-height: 100% !important;
}

不过,为了完整起见,我们可以reduce来做(因为reduce是一把Swiss-army刀,你可以任何与数组相关的东西,因为它基本上是一个循环):

const result = [...stores.reduce((byId, store) => {
    const previous = byId.get(store.id);
    if (!previous) {
        return byId.set(store.id, store);
    }
    const merchantIDs = [...new Set([...previous.merchantIDs, ...store.merchantIDs])];
    return byId.set(store.id, {
        ...previous,
        merchantIDs,
        totalMerAcc: merchantIDs.length,
    });
}, new Map()).values()];

实例:

const stores = [
    {
        id: "61f27aeb766e4b2924532f98",
        xName: 'SaurabhTest2',
        merchantIDs: ["61f27bca766e4b2924532fb3"],
        totalMerAcc: 1,
        oneTimeData: 100
    },
    {
        id: "61f2769b766e4b2924532f1f",
        xName: 'SaurabhTest',
        merchantIDs: ["61f2788e766e4b2924532f54", "61f277b8766e4b2924532f31"],
        totalMerAcc: 2,
        oneTimeData: 100
    },
    {
        id: "61f2769b766e4b2924532f1f",
        xName: 'SaurabhTest',
        merchantIDs: ["61f277b8766e4b2924532f31"],
        totalMerAcc: 1,
        oneTimeData: 100
    }
];

const result = [...stores.reduce((byId, store) => {
    const previous = byId.get(store.id);
    if (!previous) {
        return byId.set(store.id, store);
    }
    const merchantIDs = [...new Set([...previous.merchantIDs, ...store.merchantIDs])];
    return byId.set(store.id, {
        ...previous,
        merchantIDs,
        totalMerAcc: merchantIDs.length,
    });
}, new Map()).values()];
console.log(JSON.stringify(result, null, 4));
.as-console-wrapper {
    max-height: 100% !important;
}