在对象数组中合并两个对象

时间:2019-08-27 23:49:25

标签: javascript arrays object

我有以下数组:

[
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 5,
        "date": "2018-11-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 2,
        "date": "2018-11-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 1,
        "date": "2018-12-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 2,
        "date": "2018-12-27T00:00:00.000Z",
    }
]

我想基于 idItem date 合并对象并计算平均标记,这样我就可以得到以下内容:

[
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 3.5,
        "date": "2018-11-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 1.5,
        "date": "2018-12-27T00:00:00.000Z"
    }
]

4 个答案:

答案 0 :(得分:1)

尝试一下:

const input = [
  { idItem: "5d656f10394d6524c821f1b1", mark: 5, date: "2018-11-27T00:00:00.000Z" },
  { idItem: "5d656f10394d6524c821f1b1", mark: 2, date: "2018-11-27T00:00:00.000Z" },
  { idItem: "5d656f10394d6524c821f1b1", mark: 1, date: "2018-12-27T00:00:00.000Z" },
  { idItem: "5d656f10394d6524c821f1b1", mark: 2, date: "2018-12-27T00:00:00.000Z" }
];

const ids = new Set(input.map(e => `${e.idItem} ${e.date}`));
const grouped = [...ids].map(id => input.filter(
  e => `${e.idItem} ${e.date}` === id
)).map(
  group => ({
    ...group[0],
    mark: group.reduce((acc, cur) => cur.mark + acc, 0) / group.length,
  })
);

您可以看到结果已注销here

可能不是性能最高的,但是可以。首先,我们获得一组所有id和date的组合,然后过滤每个组合的输入。然后,对于每个组,我们将日期和ID复制到结果中,并减少条目以获得平均值。

答案 1 :(得分:1)

如果id和date字符串中没有逗号(,),则可以使用此解决方案,我首先生成一个对象,其中键是id和日期的串联,并且这些值是具有具有键的ID和日期以及其标记之和的元素数量的对象,然后该对象将用于构造所需的数组:

var arr = [
  { "idItem": "5d656f10394d6524c821f1b1", "mark": 5, "date": "2018-11-27T00:00:00.000Z" },
  { "idItem": "5d656f10394d6524c821f1b1", "mark": 2, "date": "2018-11-27T00:00:00.000Z" },
  { "idItem": "5d656f10394d6524c821f1b1", "mark": 1, "date": "2018-12-27T00:00:00.000Z" },
  { "idItem": "5d656f10394d6524c821f1b1", "mark": 2, "date": "2018-12-27T00:00:00.000Z" }
];

var obj = {};

arr.forEach((o) => {
  var k = o.idItem + ',' + o.date;
  if (obj.hasOwnProperty(k)) {
    obj[k].s += o.mark;
    obj[k].n += 1;
  } else {
    obj[k] = {s: o.mark, n: 1};
  }
});

var result = [];

Object.keys(obj).forEach((k) => {
  var p = k.split(',');
  result.push({idItem: p[0], date: p[1], mark: obj[k].s / obj[k].n})
});

console.log(result);

答案 2 :(得分:1)

我正在使用lodash groupBy

Object.entries(_.groupBy([
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 5,
        "date": "2018-11-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 2,
        "date": "2018-11-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 1,
        "date": "2018-12-27T00:00:00.000Z"
    },
    {
        "idItem": "5d656f10394d6524c821f1b1",
        "mark": 2,
        "date": "2018-12-27T00:00:00.000Z",
    }
], e => `${e.idItem}_${e.date}`)).reduce((acc, [key, value]) => {
  const mark = value.reduce((sum, el) => sum + el.mark, 0) / value.length
 const [idItem, date] = key.split('_')
  return [...acc, { idItem, date, mark }]
}, [])

答案 3 :(得分:0)

首先,我将声明在此示例中将使用的数组:

var array = [
   {
      "idItem": "5d656f10394d6524c821f1b1",
      "mark": 5,
      "date": "2018-11-27T00:00:00.000Z"
   },
   {
      "idItem": "5d656f10394d6524c821f1b1",
      "mark": 2,
      "date": "2018-11-27T00:00:00.000Z"
   },
   {
      "idItem": "5d656f10394d6524c821f1b1",
      "mark": 1,
      "date": "2018-12-27T00:00:00.000Z"
   },
   {
      "idItem": "5d656f10394d6524c821f1b1",
      "mark": 2,
      "date": "2018-12-27T00:00:00.000Z",
   }
];

这就是这种情况:我有一个程序可以工作,但另一个实现却几乎有效。我将从一个有效的程序开始,它使用alasql库:

要加载依赖项,请使用以下<script>标签:

<script src="https://cdn.jsdelivr.net/npm/alasql@0.4">

实施:

var newArray = alasql('SELECT idItem, AVG([mark]) AS [mark], date AS [date] 
FROM ? GROUP BY date',[array]);
console.log(JSON.stringify(newArray));

下一个程序仅计算不考虑日期的所有ID的平均值(因此得出的平均值为2.5)。也许有人可以弄清楚如何正确运行该程序并编辑我的答案:

var sum = {};
for(var i = 0; i < array.length; i++) {
   var ele = array[i];
   if (!sum[ele.idItem]) {
      sum[ele.idItem] = {};
      sum[ele.idItem]["sum"] = 0;
      sum[ele.idItem]["count"] = 0;
   }
   sum[ele.idItem]["sum"] += ele.mark;
   sum[ele.idItem]["count"]++;
}
var result = [];
for (var idItem in sum) {
    result.push({idItem: idItem, mark: sum[idItem]["sum"] / sum[idItem]["count"]});
}
console.log(JSON.stringify(result));