对对象类型数组的属性求和,然后将它们作为单个对象加入

时间:2018-12-03 08:58:33

标签: javascript arrays node.js json

需要基于使用者名称属性对不同对象的scoretotal_score求和。

输入数据:

var data = [{
  name: "One",
  maths: {
    score: 2,
    total_score: 4
  },
  science: {
    score: 2,
    total_score: 4
  },
  social: {
    score: 2,
    total_score: 4
  }
}, {
  name: "One",
  maths: {
    score: 3,
    total_score: 4
  },
  science: {
    score: 1,
    total_score: 4
  },
  english: {
    score: 4,
    total_score: 4
  }
}]

预期输出:

{
  name: "One",
  maths: {
    score: 5,
    total_score: 8
  },
  science: {
    score: 3,
    total_score: 8
  },
  social: {
    score: 2,
    total_score: 4
  },
  english: {
    score: 4,
    total_score: 4
  }
}

我已经尝试过了:

data.forEach(function (a) {
    if (!this[a.name]) {
        this[a.name] = { name: a.name, contributions: 0 };
        result.push(this[a.name]);
    }
    this[a.name].contributions += a.contributions;
}, Object.create(null));

但这不适用于我的情况。 contributions对象不同的地方,即主题名称每次都不同。

先谢谢大家!

3 个答案:

答案 0 :(得分:1)

尝试关注

  • 使用 Array.reduce 将数组转换为对象,其中键为名称,值为结果对象。然后使用 Object.values 从创建的对象中收集所有值
  • 在创建对象时,检查对象中是否存在键(名称)。如果没有,请为其添加一个条目(a[name] = a[name] || {name};)。
  • 现在,对于所有其他键(主题),使用 Object.entries 创建一个数组,并对其进行迭代以添加/更新score和total_score的值。 / li>

var data = [{name: "One", maths: {score: 2, total_score: 4}, science: {score: 2, total_score: 4}, social: {score: 2, total_score: 4}},{name: "One", maths: {score: 3, total_score: 4}, science: {score: 1, total_score: 4}, english: {score: 4, total_score: 4}}];
var result = Object.values(data.reduce((a,{name, ...rest}) => {
  a[name] = a[name] || {name};
  Object.entries(rest).forEach(([k,v]) => {
    a[name][k] = a[name][k] || {score:0, total_score:0};
    a[name][k].score += v.score;
    a[name][k].total_score += v.total_score;
  });
  return a;
},{}));
console.log(result);

答案 1 :(得分:1)

您可以使用Array.reduce()

var data = [{
    name: "One",
    maths: {
      score: 2,
      total_score: 4
    },
    science: {
      score: 2,
      total_score: 4
    },
    social: {
      score: 2,
      total_score: 4
    }
  },
  {
    name: "One",
    maths: {
      score: 3,
      total_score: 4
    },
    science: {
      score: 1,
      total_score: 4
    },
    english: {
      score: 4,
      total_score: 4
    }
  },
  {
    name: "Two",
    maths: {
      score: 3,
      total_score: 4
    },
    science: {
      score: 1,
      total_score: 4
    },
    english: {
      score: 4,
      total_score: 4
    }
  },
  {
    name: "Two",
    maths: {
      score: 3,
      total_score: 5
    },
    science: {
      score: 1,
      total_score: 5
    },
    english: {
      score: 4,
      total_score: 6
    }
  }
];
var res = data.reduce((acc, item)=>{
  var exist = acc.find(({name}) => name === item.name);
  if(exist){
    Object.keys(item).forEach((key) =>{
      if(key !== 'name'){
        if(exist[key]){
          exist[key].total_score += item[key].total_score;
          exist[key].score += item[key].score
        } else {
           exist[key] = item[key]
        }
      }
    });
  } else {
    acc.push(item);
  }
  return acc;
}, []);
console.log(res);

答案 2 :(得分:1)

您可以将数组作为减少的临时结果,并查找具有相同名称的对象并更新所有其他属性。

var data = [{ name: "One", maths: { score: 2, total_score: 4 }, science: { score: 2, total_score: 4 }, social: { score: 2, total_score: 4 } }, { name: "One", maths: { score: 3, total_score: 4 }, science: { score: 1, total_score: 4 }, english: { score: 4, total_score: 4 } }],
    result = data.reduce((r, o) => {
        var temp = r.find(({ name }) => name === o.name);
        if (!temp) {
            r.push(temp = { name: o.name });
        }
        Object.entries(o).forEach(([k, p]) => {
            if (k === 'name') return;
            temp[k] = temp[k] || {};
            ['score', 'total_score'].forEach(l => temp[k][l] = (temp[k][l] || 0) + o[k][l]);
        });
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }