如何从一组对象中,通过一个或多个不同的 属性-names / object-keys 进行一组,合并和聚合值,每个任务?
How, from an array of objects, does one group, merge and aggregate values, each task by one or more different property-names / object-keys?
我有一个对象数组如下。
我想将具有相同 bank
、gender
、age
和 state
的那些组合在一起。
我想分别求和他们的depositAmount
和withdrawalAmount
,每个计数组也是如此。 (输出中排除了user
)
示例数组
[{
"bank": "bank1",
"user": "u1",
"depositAmount": 12,
"withdrawalAmount": 33,
"gender": "male",
"age": 38,
"state": "Arizona"
},
{
"bank": "bank1",
"user": "u2",
"depositAmount": 25,
"withdrawalAmount": 44,
"gender": "male",
"age": 38,
"state": "Arizona"
},
{
"bank": "bank2",
"user": "u3",
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
}]
预期输出
[{
"bank": "bank1"
"depositAmount": 27,
"withdrawalAmount": 77,
"gender": "male",
"age": 38,
"state": "Arizona"
"count": 2
},
{
"bank": "bank2"
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
"count": 1
}]
此问题的通用解决方案是为...实施可配置的 reducer-function “它分组、合并和聚合”任务。
为了满足 OP 的要求,提供了相应定制的自定义 collector-object 作为 reduce
-method's initial value。
通用减速器期望得到一个 createKey
、一个 createMerger
和一个 aggregate
函数以及一个基于 Map
的 lookup
和一个空 result
-array 其中后者,一旦 reduce 任务已经 运行,将保存所有 grouped/merged 和聚合对象。
至于OP的具体要求,提供的功能是...
OP ...
"I would like to group those with the same bank
, gender
, age
, and state
together."
createKey: ({ bank, gender, age, state }) => [bank, gender, age, state].join('_')
OP ...
"I'd like to sum their depositAmount
and withdrawalAmount
together, respectively, and count each group as well. (user
is excluded in the output)."
createMerger: ({ bank, gender, age, state }) => ({ bank, gender, age, state, count: 0, depositAmount: 0, withdrawalAmount: 0 })
aggregate: (merger, { depositAmount, withdrawalAmount }) => { ++merger.count; merger.depositAmount += depositAmount; merger.withdrawalAmount += withdrawalAmount; }
function groupMergeAndAggregateGenerically(collector, item) {
const {
createKey, createMerger, aggregate,
lookup, result = [],
} = collector;
const key = createKey(item);
let merger = lookup.get(key) ?? null;
if (merger === null) {
merger = createMerger(item);
lookup.set(key, merger);
result.push(merger);
}
aggregate(merger, item);
return collector;
}
const sampleData = [{
"bank": "bank1",
"user": "u1",
"depositAmount": 12,
"withdrawalAmount": 33,
"gender": "male",
"age": 38,
"state": "Arizona"
}, {
"bank": "bank1",
"user": "u2",
"depositAmount": 25,
"withdrawalAmount": 44,
"gender": "male",
"age": 38,
"state": "Arizona"
}, {
"bank": "bank2",
"user": "u3",
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
}];
// OP: I would like to group those with the same
// `bank`, `gender`, `age`, and `state` together.
const createKey = ({ bank, gender, age, state }) =>
[bank, gender, age, state].join('_');
// OP: I'd like to sum their `depositAmount` and
// `withdrawalAmount` together, respectively, and
// `count` each group as well. (`user` is excluded in the output).
const createMerger = ({ bank, gender, age, state }) => ({
bank, gender, age, state, count: 0, depositAmount: 0, withdrawalAmount: 0,
});
const aggregate = (merger, { depositAmount, withdrawalAmount }) => {
++merger.count;
merger.depositAmount += depositAmount;
merger.withdrawalAmount += withdrawalAmount;
};
const { result: mergedData } = sampleData
.reduce(groupMergeAndAggregateGenerically, {
createKey,
createMerger,
aggregate,
lookup: new Map,
result: [],
});
console.log({ mergedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我有一个对象数组如下。
我想将具有相同 bank
、gender
、age
和 state
的那些组合在一起。
我想分别求和他们的depositAmount
和withdrawalAmount
,每个计数组也是如此。 (输出中排除了user
)
示例数组
[{
"bank": "bank1",
"user": "u1",
"depositAmount": 12,
"withdrawalAmount": 33,
"gender": "male",
"age": 38,
"state": "Arizona"
},
{
"bank": "bank1",
"user": "u2",
"depositAmount": 25,
"withdrawalAmount": 44,
"gender": "male",
"age": 38,
"state": "Arizona"
},
{
"bank": "bank2",
"user": "u3",
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
}]
预期输出
[{
"bank": "bank1"
"depositAmount": 27,
"withdrawalAmount": 77,
"gender": "male",
"age": 38,
"state": "Arizona"
"count": 2
},
{
"bank": "bank2"
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
"count": 1
}]
此问题的通用解决方案是为...实施可配置的 reducer-function “它分组、合并和聚合”任务。
为了满足 OP 的要求,提供了相应定制的自定义 collector-object 作为 reduce
-method's initial value。
通用减速器期望得到一个 createKey
、一个 createMerger
和一个 aggregate
函数以及一个基于 Map
的 lookup
和一个空 result
-array 其中后者,一旦 reduce 任务已经 运行,将保存所有 grouped/merged 和聚合对象。
至于OP的具体要求,提供的功能是...
OP ...
"I would like to group those with the same
bank
,gender
,age
, andstate
together."createKey: ({ bank, gender, age, state }) => [bank, gender, age, state].join('_')
OP ...
"I'd like to sum their
depositAmount
andwithdrawalAmount
together, respectively, and count each group as well. (user
is excluded in the output)."createMerger: ({ bank, gender, age, state }) => ({ bank, gender, age, state, count: 0, depositAmount: 0, withdrawalAmount: 0 })
aggregate: (merger, { depositAmount, withdrawalAmount }) => { ++merger.count; merger.depositAmount += depositAmount; merger.withdrawalAmount += withdrawalAmount; }
function groupMergeAndAggregateGenerically(collector, item) {
const {
createKey, createMerger, aggregate,
lookup, result = [],
} = collector;
const key = createKey(item);
let merger = lookup.get(key) ?? null;
if (merger === null) {
merger = createMerger(item);
lookup.set(key, merger);
result.push(merger);
}
aggregate(merger, item);
return collector;
}
const sampleData = [{
"bank": "bank1",
"user": "u1",
"depositAmount": 12,
"withdrawalAmount": 33,
"gender": "male",
"age": 38,
"state": "Arizona"
}, {
"bank": "bank1",
"user": "u2",
"depositAmount": 25,
"withdrawalAmount": 44,
"gender": "male",
"age": 38,
"state": "Arizona"
}, {
"bank": "bank2",
"user": "u3",
"depositAmount": 10,
"withdrawalAmount": 0,
"gender": "male",
"age": 38,
"state": "Florida"
}];
// OP: I would like to group those with the same
// `bank`, `gender`, `age`, and `state` together.
const createKey = ({ bank, gender, age, state }) =>
[bank, gender, age, state].join('_');
// OP: I'd like to sum their `depositAmount` and
// `withdrawalAmount` together, respectively, and
// `count` each group as well. (`user` is excluded in the output).
const createMerger = ({ bank, gender, age, state }) => ({
bank, gender, age, state, count: 0, depositAmount: 0, withdrawalAmount: 0,
});
const aggregate = (merger, { depositAmount, withdrawalAmount }) => {
++merger.count;
merger.depositAmount += depositAmount;
merger.withdrawalAmount += withdrawalAmount;
};
const { result: mergedData } = sampleData
.reduce(groupMergeAndAggregateGenerically, {
createKey,
createMerger,
aggregate,
lookup: new Map,
result: [],
});
console.log({ mergedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }