合并不同长度的对象

Merging objects of different lengths

我有一个对象数组,以日期字符串为键,布局如下:

[
    {
        '2017-08-21': {row: 0, artind: 25, qind: 20}, 
        '2017-08-22': {row: 1, artind: 5, qind: 12}, 
        '2017-08-23': {row: 11, artind: 3, qind: 0}, 
        '2017-08-24': {row: 45, artind: 25, qind: 43}, 
        '2017-08-25': {row: 13, artind: 0, qind: 27}, 
        '2017-08-26': {row: 2, artind: 2, qind: 2}, 
        '2017-08-27': {row: 1, artind: 12, qind: 27}, 
        '2017-08-28': {row: 19, artind: 0, qind: 0}, 
        '2017-08-29': {row: 11, artind: 25, qind: 7}
    },
    {
        '2017-08-24': {row: 1, artind: 34, qind: 8}, 
        '2017-08-25': {row: 0, artind: 5, qind: 3}, 
        '2017-08-26': {row: 7, artind: 22, qind: 0}
    },
    {
        '2017-08-22': {row: 55, artind: 5, qind: 2}, 
        '2017-08-23': {row: 13, artind: 25, qind: 0}, 
        '2017-08-24': {row: 1, artind: 0, qind: 0}, 
        '2017-08-25': {row: 6, artind: 8, qind: 0}, 
        '2017-08-26': {row: 0, artind: 12, qind: 89}, 
        '2017-08-27': {row: 11, artind: 29, qind: 5}
    }
]

我需要对每个对象中的所有值求和。所以最后,我需要一个看起来像这样的对象:

{
    '2017-08-21': {row: 0, artind: 25, qind: 20}, 
    '2017-08-22': {row: 56, artind: 10, qind: 14}, 
    '2017-08-23': {row: 24, artind: 28, qind: 0}, 
    '2017-08-24': {row: 47, artind: 59, qind: 51}, 
    '2017-08-25': {row: 19, artind: 13, qind: 30}, 
    '2017-08-26': {row: 9, artind: 36, qind: 91}, 
    '2017-08-27': {row: 12, artind: 41, qind: 32}, 
    '2017-08-28': {row: 19, artind: 0, qind: 0}, 
    '2017-08-29': {row: 11, artind: 25, qind: 7}
}

我真正用于支持的唯一库是 underscore.js,所以非常感谢这些答案!

谢谢

您可以使用以下reduce方法来解决您的问题。

const a = [{
  '2017-08-21': { row: 0, artind: 25, qind: 20 },
  '2017-08-22': { row: 1, artind: 5, qind: 12 },
  '2017-08-23': { row: 11, artind: 3, qind: 0 },
  '2017-08-24': { row: 45, artind: 25, qind: 43 },
  '2017-08-25': { row: 13, artind: 0, qind: 27 },
  '2017-08-26': { row: 2, artind: 2, qind: 2 },
  '2017-08-27': { row: 1, artind: 12, qind: 27 },
  '2017-08-28': { row: 19, artind: 0, qind: 0 },
  '2017-08-29': { row: 11, artind: 25, qind: 7 }
},
{
  '2017-08-24': { row: 1, artind: 34, qind: 8 },
  '2017-08-25': { row: 0, artind: 5, qind: 3 },
  '2017-08-26': { row: 7, artind: 22, qind: 0 }
},
{
  '2017-08-22': { row: 55, artind: 5, qind: 2 },
  '2017-08-23': { row: 13, artind: 25, qind: 0 },
  '2017-08-24': { row: 1, artind: 0, qind: 0 },
  '2017-08-25': { row: 6, artind: 8, qind: 0 },
  '2017-08-26': { row: 0, artind: 12, qind: 89 },
  '2017-08-27': { row: 11, artind: 29, qind: 5 }
}];

a.reduce((result, item) => {
  Object.keys(item).forEach((key) => {
    if (result[key]) {
      result[key] = {
        row: result[key].row + item[key].row,
        artind: result[key].artind + item[key].artind,
        qind: result[key].qind + item[key].qind };
    } else {
      result[key] = item[key];
    }
  });
  return result;
}, {});

编辑:只是格式化

我不确定这是最好的方法,但我会这样做。

假设变量 detain 包含您的数据,而 dataout 是您的输出。

var datain = [
  {
    '2017-08-21': {row: 0, artind: 25, qind: 20},
    '2017-08-22': {row: 1, artind: 5, qind: 12},
    '2017-08-23': {row: 11, artind: 3, qind: 0},
    '2017-08-24': {row: 45, artind: 25, qind: 43},
    '2017-08-25': {row: 13, artind: 0, qind: 27},
    '2017-08-26': {row: 2, artind: 2, qind: 2},
    '2017-08-27': {row: 1, artind: 12, qind: 27},
    '2017-08-28': {row: 19, artind: 0, qind: 0},
    '2017-08-29': {row: 11, artind: 25, qind: 7}
  },
  {
    '2017-08-24': {row: 1, artind: 34, qind: 8},
    '2017-08-25': {row: 0, artind: 5, qind: 3},
    '2017-08-26': {row: 7, artind: 22, qind: 0}
  },
  {
    '2017-08-22': {row: 55, artind: 5, qind: 2},
    '2017-08-23': {row: 13, artind: 25, qind: 0},
    '2017-08-24': {row: 1, artind: 0, qind: 0},
    '2017-08-25': {row: 6, artind: 8, qind: 0},
    '2017-08-26': {row: 0, artind: 12, qind: 89},
    '2017-08-27': {row: 11, artind: 29, qind: 5}
  }
];

var dataout = { };

for(set=0; set<datain.length; set++)
{
    for(date in datain[set])
    {
        for(field in datain[set][date])
        {
            if ( typeof dataout[date] === 'undefined' ) { dataout[date] = { }; }
            if ( typeof dataout[date][field] === 'undefined' ) { dataout[date][field] = 0; }
            dataout[date][field] += datain[set][date][field];
        }
    }
}
console.log(data out);

这给您带来的结构灵活性很小,因此这实际上取决于您的数据是否会发生变化。

这里有一个使用 Lodash 的解决方案,它与 Underscore 非常相似。您应该能够非常轻松地翻译调用(或者只使用 Lodash,因为它更快更好;))

基本上您要做的是展平嵌套对象,找到一种可以按日期分组的方法,然后对内部值求和。

如果下面的任何代码不清楚,请告诉我。

let items = [
    {
        '2017-08-21': {row: 0, artind: 25, qind: 20},
        '2017-08-22': {row: 1, artind: 5, qind: 12},
        '2017-08-23': {row: 11, artind: 3, qind: 0},
        '2017-08-24': {row: 45, artind: 25, qind: 43},
        '2017-08-25': {row: 13, artind: 0, qind: 27},
        '2017-08-26': {row: 2, artind: 2, qind: 2},
        '2017-08-27': {row: 1, artind: 12, qind: 27},
        '2017-08-28': {row: 19, artind: 0, qind: 0},
        '2017-08-29': {row: 11, artind: 25, qind: 7}
    },
    {
        '2017-08-24': {row: 1, artind: 34, qind: 8},
        '2017-08-25': {row: 0, artind: 5, qind: 3},
        '2017-08-26': {row: 7, artind: 22, qind: 0}
    },
    {
        '2017-08-22': {row: 55, artind: 5, qind: 2},
        '2017-08-23': {row: 13, artind: 25, qind: 0},
        '2017-08-24': {row: 1, artind: 0, qind: 0},
        '2017-08-25': {row: 6, artind: 8, qind: 0},
        '2017-08-26': {row: 0, artind: 12, qind: 89},
        '2017-08-27': {row: 11, artind: 29, qind: 5}
    }
]

const groupedItems = _(items)
    // get the nested objects, break them out, and give them date and value keys that we can use later
    .map(item =>{
      const keys = Object.keys(item);
      return _.map(keys, key => {
        return {
          date: key, // i.e. date: 2017-08-22
          value: item[key] // i.e. value: {row: 1, artind: 5, qind: 12}
        }
      })
    })
    // flatten all the nested items into one array
    .flatten()
    // group by the date key we created earlier i.e. 2017-08-22 : [array with 2 entries]
    .groupBy(item => item.date)
    // take each of these dateItems, and internally sum their individual nested values, then return
    .map(dateItem => {
      const date = dateItem[0].date; // just grab the first date value, we'll use that as our final key
      const row = _.sumBy(dateItem, innerItem => innerItem.value.row);
      const artind = _.sumBy(dateItem, innerItem => innerItem.value.artind);
      const qind = _.sumBy(dateItem, innerItem => innerItem.value.qind);
      const returnObject = {
        [date]: {row, artind, qind}
      };
      return(returnObject);
    })
    // call valueOf to execute the chain
    .valueOf();


    console.log(groupedItems);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

我将添加到您的答案列表中。只有这个片段添加了默认值以防止未定义。

var arr = [
    {
        '2017-08-21': { artind: 25, qind: 20 },
        '2017-08-22': { row: 1, artind: 5, qind: 12 },
        '2017-08-23': { row: 11, artind: 3, qind: 0 },
        '2017-08-24': { row: 45, artind: 25, qind: 43 },
        '2017-08-25': { row: 13, artind: 0, qind: 27 },
        '2017-08-26': { row: 2, artind: 2, qind: 2 },
        '2017-08-27': { row: 1 },
        '2017-08-28': { row: 19, artind: 0, qind: 0 },
        '2017-08-29': { row: 11, artind: 25, qind: 7 }
    },
    {
        '2017-08-24': { row: 1, artind: 34, qind: 8 },
        '2017-08-25': { row: 0, artind: 5, qind: 3 },
        '2017-08-26': { row: 7, artind: 22, qind: 0 }
    },
    {
        '2017-08-22': { artind: 5, qind: 2 },
        '2017-08-23': { row: 13, artind: 25, qind: 0 },
        '2017-08-24': { row: 1},
        '2017-08-25': { row: 6, artind: 8, qind: 0 },
        '2017-08-26': { row: 0, artind: 12, qind: 89 },
        '2017-08-27': { row: 11, artind: 29, qind: 5 }
    }
];
var acc = _.reduce(arr, function (acc, elem) {
            _.each(elem, function (value, key) {
                _.defaults(value, {row: 0, artind:0 , qind: 0});
                if (_.has(acc, key)) {
                    acc[key].row += value.row;
                    acc[key].artind += value.artind;
                    acc[key].qind += value.qind;
                }
                else {
                    acc[key] = value;
                }
            });
            return acc;
          }, {});
console.log(acc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

.