JavaScript:按通用项目字段组合项目值列表

时间:2019-03-05 02:07:56

标签: javascript arrays json

我正在尝试合并list数组中的项目,以便在结果数组中仅存在唯一的date字段。我还需要结果数组中的amount项字段是原始数组中共享相同date值的所有项的总和。

我的list数组中的数据格式如下:

var list = [
  {amount: "10", date: "2000-03-01"},// These three records have same date 
  {amount: "20", date: "2000-03-01"},// field, need to combine into
  {amount: "30", date: "2000-03-01"},// one record
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"},
  {amount: "30", date: "2000-03-06"},// These two records have same date 
  {amount: "70", date: "2000-03-06"},// field, need to combine
  {amount: "80", date: "2000-03-10"},
]

我需要将上面的列表转换为此:

var expectedList = [
  {amount: "60", date: "2000-03-01"}, // combined item
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"},
  {amount: "100", date: "2000-03-06"},// combined item
  {amount: "80", date: "2000-03-10"},
]

5 个答案:

答案 0 :(得分:4)

一个解决方案可能是通过Array.reduce()进行,其中您将首先构建一个中间映射,该映射将date键映射到总计amount个值。然后,您可以通过Object.entries()将映射转换回平面数组,如下所示:

var list = [
  {amount: "10", date: "2000-03-01"},
  {amount: "20", date: "2000-03-01"},
  {amount: "30", date: "2000-03-01"},
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"},
]

const result = Object.entries(list.reduce((mapping, item) => {
  
  /* During each iteration of reduce over the list, retrieve
  the totalled "amount" for this item's "date" */
  mapping[ item.date ] = mapping[ item.date ] || 0
  
  /* Increment the "total" for this "date" by the "amount" of
  the current item, and persist into the map */
  mapping[ item.date ] += Number.parseInt(item.amount)
  
  return mapping
  
}, {})).map(([amount, date]) => {
  
  /* Object.entries() returns a list of key/value pairs from the 
  mapping created by our reduce() step. Here we transform each
  key/value pair of the mapping back to the desired format */
  return { amount, date }
});

console.log(result)

答案 1 :(得分:2)

您可以使用reduce函数来实现。

list.reduce(( prev, curr )=>{
    // parse string amount into number for calculation
    curr.amount = parseInt(curr.amount);

    let index;

    if ((index = prev.findIndex( item => item.date == curr.date )) > -1 )
        prev[index].amount += curr.amount;
    else
        prev.push( curr );

    return prev;

}, []);

输出:

[ { amount: 60, date: '2000-03-01' },
  { amount: 50, date: '2000-03-03' },
  { amount: 100, date: '2000-03-05' } ]

答案 2 :(得分:2)

如果您想要简单易懂的代码,请使用下面的代码段。

下面的代码基本上遍历列表,然后遍历输出以检查两个元素中的日期是否相同。如果是这样,它将添加金额并将found的值设置为true。在.forEach()的末尾,如果found仍然为false(如果我们没有找到日期匹配的元素),则将值推入输出数组。

var list = [
  {amount: "10", date: "2000-03-01"},
  {amount: "20", date: "2000-03-01"},
  {amount: "30", date: "2000-03-01"},
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"},
]
var output = [];
var found = false;

list.forEach(e1 => {
  found = false;
  output.forEach(e2 => {
    if (e1.date == e2.date) {
      e2.amount = parseInt(e2.amount) + parseInt(e1.amount);
      found = true;
    }
  });
  
  if (!found) {
    output.push(e1);
  }
});

console.log(output);

答案 3 :(得分:2)

似乎是一个相当简单的两步过程。首先,将数组简化为日期与金额总和的映射,然后将该映射的值转换为新的数组。

var list = [
  {amount: "10", date: "2000-03-01"},
  {amount: "20", date: "2000-03-01"},
  {amount: "30", date: "2000-03-01"},
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"}
]

const expectedList = Array.from(list.reduce((map, {amount, date}) => {
  return map.set(date, (map.get(date) || 0) + parseInt(amount))
}, new Map())).map(([date, amount]) => ({ amount, date }))

console.info(expectedList)

答案 4 :(得分:1)

var list = [
  {amount: "10", date: "2000-03-01"},
  {amount: "20", date: "2000-03-01"},
  {amount: "30", date: "2000-03-01"},
  {amount: "50", date: "2000-03-03"},
  {amount: "100", date: "2000-03-05"},
]

const builtObject = list.reduce((acc, {date, amount}) => {
  acc[date] = acc[date] || 0
  acc[date] += parseInt(amount)
  return acc
}, {})

const rs = Object.entries(builtObject).map(([date, amount]) => ({amount, date}))

console.log(rs)