[英]Javascript: Merge Objects in array with different key/value pairs, and getitng the sum from the same keys
So what I have is an array of objects所以我有一个对象数组
[
{
"email": "jacob@whatever.com",
"actionsCount": {
"edit record": 5,
"assign to specialist": 1
},
"changesTotal": 6
},
{
"email": "trav1@whatever.com",
"actionsCount": {
"edit record": 13,
"duplicate": 5,
"return for changes": 1
},
"changesTotal": 19
},
{
"email": "donbossman@whatever.com",
"actionsCount": {
"edit record": 5
},
"changesTotal": 5
},
{
"email": "donbossman@whatever.com",
"actionsCount": {
"edit record": 11,
"return for changes": 1,
"assign to specialist": 1
},
"changesTotal": 13
},
{
"email": "Marilla@whatever.com",
"actionsCount": {
"edit record": 7
},
"changesTotal": 7
},
{
"email": "Marilla@whatever.com",
"actionsCount": {
"edit record": 6
},
"changesTotal": 6
},
{
"email": "natalie1@whatever.com",
"actionsCount": {
"edit record": 5,
"assign to specialist": 1
},
"changesTotal": 6
},
{
"email": "natalie1@whatever.com",
"actionsCount": {
"assign to specialist": 2,
"edit record": 17
},
"changesTotal": 19
},
{
"email": "psteacher@whatever.com",
"actionsCount": {
"edit record": 2,
"assign to specialist": 2
},
"changesTotal": 4
},
{
"email": "psteacher@whatever.com",
"actionsCount": {
"edit record": 17,
"duplicate": 2
},
"changesTotal": 19
}
]
As you can see there will be multiple entries under the same email, these correspond to each month that user did some actions, as such new entries will populate each month, some most of them by the same users.如您所见,在同一个 email 下会有多个条目,这些条目对应于用户每个月执行的某些操作,因此每个月都会填充新条目,其中大部分都是由相同的用户创建的。 I don't know all of the actions, but I can be assured that the actions will all be spelled the same.
我不知道所有的动作,但我可以保证这些动作的拼写都是一样的。 The data is old so as you can see someone used spaces for the key which is another task for another day.
数据很旧,因此您可以看到有人使用空格作为密钥,这是另一天的另一项任务。
I want to combine objects by the same email, then sum the same actions across the months, and add actions that are present in one month but not another.我想按相同的 email 组合对象,然后对几个月内的相同操作求和,并添加一个月内存在但另一个月内不存在的操作。
So as an example donbossman@whatever.com
end result would look like因此,例如
donbossman@whatever.com
最终结果看起来像
Would look like看起来像
[{
"email": "donbossman@whatever.com",
"actionsCount": {
"edit record": 16,
"return for changes": 1,
"assign to specialist": 1
}
"changesTotal": 18
}]
So because edit record
is present in both occurrences of actionsCount
they are simply added up, and return for changes
and assign to specialist
are present in one but not the other因此,因为
edit record
在两次出现的actionsCount
中都存在,所以它们被简单地加起来,并且return for changes
和assign to specialist
出现在一个而不是另一个中
Right now I feel like I'm close to what I'm trying to achieve?现在我觉得我离我想要达到的目标很近了? My current approach is as follows
我目前的做法如下
tier2CollectorsActions.reduce((acc, {email, actionsCount}) => {
acc[email] ??= {email: email, actionsCount: []};
if(Array.isArray(actionsCount))
acc[email].actionsCount = _.merge(acc[email].actionsCount, actionsCount)
else
acc[email].actionsCount.push(actionsCount);
return acc;
}, {})
Which gives me back这让我回来
{
"email": "natalie1@whatever.com",
"actionsCount": [
{
"edit record": 5,
"assign to specialist": 1
},
{
"assign to specialist": 2,
"edit record": 17
}
]
}
As you can see each actionsCount
array corresponds to the two separate natalie1@whatever.com
object's actionsCount
data.如您所见,每个
actionsCount
数组对应于两个单独的natalie1@whatever.com
对象的actionsCount
数据。 I need the actionsCount data back not as an array but an object, I'm doing it as an array in the example bc its so far been the only way I can get the data from both actionCounts
.我需要的 actionsCount 数据不是作为数组而是作为 object 返回,我在示例中将其作为数组 bc 到目前为止,这是我可以从两个
actionCounts
获取数据的唯一方法。 I've been trying to use Object.value and reduce but I haven't quite gotten yet but I feel like I'm so close.我一直在尝试使用 Object.value 并减少,但我还没有完全理解,但我觉得我已经很接近了。
Any direction/tips/suggestions would be much appreciated任何方向/提示/建议将不胜感激
You were close.你很接近。
actionsCount
is always an object, never an arrayactionsCount
始终是 object,而不是数组 const data = [{ "email": "jacob@whatever.com", "actionsCount": { "edit record": 5, "assign to specialist": 1 }, "changesTotal": 6 }, { "email": "trav1@whatever.com", "actionsCount": { "edit record": 13, "duplicate": 5, "return for changes": 1 }, "changesTotal": 19 }, { "email": "donbossman@whatever.com", "actionsCount": { "edit record": 5 }, "changesTotal": 5 }, { "email": "donbossman@whatever.com", "actionsCount": { "edit record": 11, "return for changes": 1, "assign to specialist": 1 }, "changesTotal": 13 }, { "email": "Marilla@whatever.com", "actionsCount": { "edit record": 7 }, "changesTotal": 7 }, { "email": "Marilla@whatever.com", "actionsCount": { "edit record": 6 }, "changesTotal": 6 }, { "email": "natalie1@whatever.com", "actionsCount": { "edit record": 5, "assign to specialist": 1 }, "changesTotal": 6 }, { "email": "natalie1@whatever.com", "actionsCount": { "assign to specialist": 2, "edit record": 17 }, "changesTotal": 19 }, { "email": "psteacher@whatever.com", "actionsCount": { "edit record": 2, "assign to specialist": 2 }, "changesTotal": 4 }, { "email": "psteacher@whatever.com", "actionsCount": { "edit record": 17, "duplicate": 2 }, "changesTotal": 19 } ] const result = data.reduce((acc, { email, actionsCount, changesTotal }) => { acc[email]??= { email: email, actionsCount: {}, changesTotal: 0 }; Object.entries(actionsCount).forEach(([key, value]) => { acc[email].actionsCount[key]??= 0 acc[email].actionsCount[key] += value }) acc[email].changesTotal += changesTotal return acc; }, {}) console.log(result)
Use lodash's _.groupBy()
to group the items by email, and then map the groups and merge them using _.mergeWith()
.使用 lodash 的
_.groupBy()
将项目按 email 分组,然后按 map 分组并使用_.mergeWith()
合并它们。 In the customizer function of _.mergeWith()
check if either of the values is a number (since one of them might be undefined
), and if they are numbers sum them.在
_.mergeWith()
的定制器 function 中,检查两个值中的任何一个是否为数字(因为其中一个可能是undefined
),如果它们是数字,则对它们求和。 If not, let _.mergeWith()
handle them by return undefined
:如果没有,让
_.mergeWith()
通过返回undefined
来处理它们:
const { flow, groupBy, map, mergeWith, isNumber } = _ const fn = flow( arr => groupBy(arr, 'email'), groups => map(groups, items => mergeWith(...items, (o1, o2) => isNumber(o1) || isNumber(o2)? (o1?? 0) + (o2?? 0): undefined )) ) const arr = [{"email":"jacob@whatever.com","actionsCount":{"edit record":5,"assign to specialist":1},"changesTotal":6},{"email":"trav1@whatever.com","actionsCount":{"edit record":13,"duplicate":5,"return for changes":1},"changesTotal":19},{"email":"donbossman@whatever.com","actionsCount":{"edit record":5},"changesTotal":5},{"email":"donbossman@whatever.com","actionsCount":{"edit record":11,"return for changes":1,"assign to specialist":1},"changesTotal":13},{"email":"Marilla@whatever.com","actionsCount":{"edit record":7},"changesTotal":7},{"email":"Marilla@whatever.com","actionsCount":{"edit record":6},"changesTotal":6},{"email":"natalie1@whatever.com","actionsCount":{"edit record":5,"assign to specialist":1},"changesTotal":6},{"email":"natalie1@whatever.com","actionsCount":{"assign to specialist":2,"edit record":17},"changesTotal":19},{"email":"psteacher@whatever.com","actionsCount":{"edit record":2,"assign to specialist":2},"changesTotal":4},{"email":"psteacher@whatever.com","actionsCount":{"edit record":17,"duplicate":2},"changesTotal":19}] const result = fn(arr) console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
You shouldn't initialize actionsCount
to an array.您不应该将
actionsCount
初始化为数组。 That's causing it to push each actionsCount
object onto the array, instead of combining the properties.这导致它将每个
actionsCount
object 推入数组,而不是组合属性。
You need to loop over the properties in actionsCount
, adding them to the corresponding value in acc[email]
.您需要遍历
actionsCount
中的属性,将它们添加到acc[email]
中的相应值。
const tier2CollectorsActions = [{ "email": "jacob@whatever.com", "actionsCount": { "edit record": 5, "assign to specialist": 1 }, "changesTotal": 6 }, { "email": "trav1@whatever.com", "actionsCount": { "edit record": 13, "duplicate": 5, "return for changes": 1 }, "changesTotal": 19 }, { "email": "donbossman@whatever.com", "actionsCount": { "edit record": 5 }, "changesTotal": 5 }, { "email": "donbossman@whatever.com", "actionsCount": { "edit record": 11, "return for changes": 1, "assign to specialist": 1 }, "changesTotal": 13 }, { "email": "Marilla@whatever.com", "actionsCount": { "edit record": 7 }, "changesTotal": 7 }, { "email": "Marilla@whatever.com", "actionsCount": { "edit record": 6 }, "changesTotal": 6 }, { "email": "natalie1@whatever.com", "actionsCount": { "edit record": 5, "assign to specialist": 1 }, "changesTotal": 6 }, { "email": "natalie1@whatever.com", "actionsCount": { "assign to specialist": 2, "edit record": 17 }, "changesTotal": 19 }, { "email": "psteacher@whatever.com", "actionsCount": { "edit record": 2, "assign to specialist": 2 }, "changesTotal": 4 }, { "email": "psteacher@whatever.com", "actionsCount": { "edit record": 17, "duplicate": 2 }, "changesTotal": 19 } ]; const result = tier2CollectorsActions.reduce((acc, { email, actionsCount }) => { acc[email]??= { email: email, actionsCount: {} }; Object.entries(actionsCount).forEach(([key, value]) => { acc[email].actionsCount[key] = (acc[email].actionsCount[key] || 0) + value; }); return acc; }, {}) console.log(result);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.