合并同一数组的 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;
}
我尝试调查它,但找不到适合我的场景的具体用例。我相信这很简单,但我坚持了好几天。任何帮助将不胜感激
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;
}