按用户ID减少对象数组并对某些值进行求和

3

我有一个对象数组,长这样:

"data": [
{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20,"shotsMade": 19, "id": 1 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 },
{ "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 },
{ "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 },
{ "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 }
]

我想创建一个新的对象数组,其中我

  • 将user_ids减少到每个唯一用户
  • 然后计算每个用户的总shotAttempts和shotsMade

就像这样:

"dataTotals" : [
{"id": 1, "user_id": 1, "shotAttempts": 90, "shotsMade": 64}
{"id": 2, "user_id": 5, "shotAttempts": 10, "shotsMade": 9}
{"id": 3, "user_id": 6, "shotAttempts": 50, "shotsMade": 29}

我打算使用 .map 函数迭代这个新数组中的对象,以便在更多用户记录他们的数据时填充排行榜。
基于我对 .map 和 .reduce 方法的阅读,以及在此处搜索的结果,我尝试了几种不同的方法来实现这一点,但只找到了一个接近目标的方法,它返回一个如下所示的对象。
像这样:
// create new object to store results in
let newObj = {};
// loop through user objects
this.state.shotlogs.forEach(function(shotlog){
// check if user_id  has already been added to newObj
if(!newObj[shotlog.user_id]){
// If it is the first time seeing this user_id
// we need to add shots attempted and shots made to prevent errors
newObj[shotlog.user_id] = {};
newObj[shotlog.user_id]['user_id'] = shotlog.user_id;
newObj[shotlog.user_id]['shotAttempts'] = 0;
newObj[shotlog.user_id]['shotsMade'] = 0;
}
// add shots attempted and made to newObj for this user
newObj[shotlog.user_id]['shotAttempts'] += shotlog.shotAttempts
newObj[shotlog.user_id]['shotsMade'] += shotlog.shotsMade
})

但是这将返回一个看起来像这样的对象,而不是像上面那样的对象数组:
{
1: {user_id: 1, shotAttempts: 70, shotsMade: 64}
5: {user_id: 5, shotAttempts: 10, shotsMade: 9}
6: {user_id: 6, shotAttempts: 50, shotsMade: 29}
}

非常感谢您对这位新编码人员的帮助!

1
使用 Object.values(newObj) 将其值作为数组获取。 - slider
2
那似乎正是我需要的!谢谢!!! - bnilsen
3个回答

3

const data = [
  { workout_id: 1, user_id: 1, shotLocation: 27, shotAttempts: 20, shotsMade: 19, id: 1 },
  { workout_id: 2, user_id: 1, shotLocation: 1, shotAttempts: 10, shotsMade: 9, id: 2 },
  { workout_id: 2, user_id: 1, shotLocation: 10, shotAttempts: 10, shotsMade: 7, id: 3 },
  { workout_id: 2, user_id: 1, shotLocation: 1, shotAttempts: 30, shotsMade: 29, id: 4 },
  { workout_id: 3, user_id: 5, shotLocation: 1, shotAttempts: 10, shotsMade: 9, id: 5 },
  { workout_id: 4, user_id: 6, shotLocation: 1, shotAttempts: 30, shotsMade: 15, id: 6 },
  { workout_id: 4, user_id: 6, shotLocation: 2, shotAttempts: 20, shotsMade: 14, id: 7 }
];

const shooters = data.reduce(
  (results, current) => ({
    ...results,
    [current.user_id]: {
      user_id: current.user_id,
      shotAttempts: current.shotAttempts + (results[current.user_id] ? results[current.user_id].shotAttempts : 0),
      shotsMade: current.shotsMade + (results[current.user_id] ? results[current.user_id].shotsMade : 0)
    }
  }),
  {}
);

console.log(shooters);


2
你可以使用ES6解构,结合Array.reduceObject.values,以简洁的方式解决这个问题。

const data = [{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20, "shotsMade": 19, "id": 1 }, { "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 }, { "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 }, { "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 }, { "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 }, { "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 }, { "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 } ]

const result = data.reduce((r,{workout_id, user_id, shotAttempts, shotsMade}) => {
 r[user_id] = r[user_id] || {id: workout_id, user_id, shotAttempts: 0, shotsMade: 0}
 r[user_id].shotAttempts += shotAttempts
 r[user_id].shotsMade += shotsMade
 return r
}, {})

console.log(Object.values(result))


1

你可以使用Array.prototype.reduce()

代码:

const data = [{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20,"shotsMade": 19, "id": 1 },{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 },{ "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 },{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 },{ "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 },{ "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 },{ "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 }];
const dataTotals = Object.values(data.reduce((a, c) => {
  if (!a[c.user_id]) {
    a[c.user_id] = {
      id: c.workout_id,
      user_id: c.user_id,
      shotAttempts: c.shotAttempts,
      shotsMade: c.shotsMade
    };
  } else {  
    a[c.user_id].shotAttempts += c.shotAttempts;
    a[c.user_id].shotsMade += c.shotsMade;
  }
  return a;
}, {}));

console.log(dataTotals);


谢谢。我还没有尝试过这个,但我注意到可能需要进行一个更改...id: c.workout_id 可能需要变成 id: c.id - bnilsen
不是的,它只会在对象创建时使用一次,具体位置就在id: c.workout_id这一行。 - Yosvel Quintero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接