最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Combining Like Objects by Date in JavaScript Array - Stack Overflow

programmeradmin5浏览0评论

I have the following array:

var objArray = [
    { num: 1, date: '1/12/2017' },
    { num: 3, date: '1/12/2017' },
    { num: 7, date: '1/12/2017' },
    { num: 1, date: '1/13/2018' },
    { num: 3, date: '1/16/2018' },
    { num: 4, date: '1/16/2018' }
   ];

I want to bine those with same dates so that the output array looks like this:

var outputArr = [
    { num: 11, date: '1/12/2017' },
    { num: 1,  date: '1/13/2018' },
    { num: 7,  date: '1/16/2018' }
   ];

I'm adding all num with similar dates and creating a single new object.

I have a very large dataset of objects like this so I'm trying to reduce the amount of processing time for this.

I've got the arrays sorted by date so that it mirrors objArray.

For loops seems cumbersome since I'm taking the first date in the array and checking every other element in the array a la the following pseudo-code:

var newArr = [];
for(i = 0; i < objArray.length; i++) {
    for(j = 0; j < objArray.length; j++) {
        var tempArr = [];
        // check every date manually
        // add similar to new array
        tempArr.push({ similar items });
    }
    newArr.push(tempArr):
}

// Do another couple loops to bine those like arrays into another array    

There has to be a more elegant way to perform this than running multiple for loops.

Any suggestions would be appreciated.

I have the following array:

var objArray = [
    { num: 1, date: '1/12/2017' },
    { num: 3, date: '1/12/2017' },
    { num: 7, date: '1/12/2017' },
    { num: 1, date: '1/13/2018' },
    { num: 3, date: '1/16/2018' },
    { num: 4, date: '1/16/2018' }
   ];

I want to bine those with same dates so that the output array looks like this:

var outputArr = [
    { num: 11, date: '1/12/2017' },
    { num: 1,  date: '1/13/2018' },
    { num: 7,  date: '1/16/2018' }
   ];

I'm adding all num with similar dates and creating a single new object.

I have a very large dataset of objects like this so I'm trying to reduce the amount of processing time for this.

I've got the arrays sorted by date so that it mirrors objArray.

For loops seems cumbersome since I'm taking the first date in the array and checking every other element in the array a la the following pseudo-code:

var newArr = [];
for(i = 0; i < objArray.length; i++) {
    for(j = 0; j < objArray.length; j++) {
        var tempArr = [];
        // check every date manually
        // add similar to new array
        tempArr.push({ similar items });
    }
    newArr.push(tempArr):
}

// Do another couple loops to bine those like arrays into another array    

There has to be a more elegant way to perform this than running multiple for loops.

Any suggestions would be appreciated.

Share Improve this question asked Aug 20, 2018 at 17:54 razorsyntaxrazorsyntax 3593 gold badges8 silver badges44 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 5

Simply use Array.reduce() to create a map and group values by date, Object.values() on the map will give you the desired output value:

let arr = [ { num: 1, date: '1/12/2017' }, { num: 3, date: '1/12/2017' }, { num: 7, date: '1/12/2017' }, { num: 1, date: '1/13/2018' }, { num: 3, date: '1/16/2018' }, { num: 4, date: '1/16/2018' } ];
   
let result = Object.values(arr.reduce((a, {num, date})=>{
  if(!a[date])
    a[date] = Object.assign({},{num, date});
   else
    a[date].num += num;
  return a;
 },{}));
 console.log(result);

Using lodash,

// Aggregate num from unique dates
var g = _.groupBy(objArray,'date')
Object.keys(g).map(k=>({num:g[k].reduce((a,c)=>c.num+a,0),date:k})) 
var objArray = [
    { num: 1, date: '1/12/2017' },
    { num: 3, date: '1/12/2017' },
    { num: 7, date: '1/12/2017' },
    { num: 1, date: '1/13/2018' },
    { num: 3, date: '1/16/2018' },
    { num: 4, date: '1/16/2018' }
   ];

let outputArr = Array.from(objArray.reduce((acc, obj)=>{
  acc.set(obj.date, (acc.get([obj.date]) || 0) + obj.num);
  return acc;
}, new Map()))
.map(kv=>({num: kv[1], date: kv[0]}))

console.log(outputArr);

gives:

[ { num: 11, date: '1/12/2017' },
  { num: 1, date: '1/13/2018' },
  { num: 7, date: '1/16/2018' } ]

You could also remove the if statements and use a Set if you wanted to be even more declarative.

var objArray = [
    { num: 1, date: '1/12/2017' },
    { num: 3, date: '1/12/2017' },
    { num: 7, date: '1/12/2017' },
    { num: 1, date: '1/13/2018' },
    { num: 3, date: '1/16/2018' },
    { num: 4, date: '1/16/2018' }
];
var mSet = new Set(objArray.map(d => d.date));
return Array.from(mSet).map(d => {
    return
    { 
        date: d,
        sum: (objArray
            .filter(o => o.date === d)
            .map(n => n.num)
            .reduce((a, c) => a + c, 0))
    }
);

This returns:

[{ date: 1/12/2017, sum: 11},
{ date: 1/13/2018, sum: 1 },
{ date: 1/16/2018, sum: 7 }]

Here's another way. It's more verbose, but if you're just starting out it might be easier to understand as opposed to using array methods like reduce().

objArray = [
    { num: 1, date: '1/12/2017' },
    { num: 3, date: '1/12/2017' },
    { num: 7, date: '1/12/2017' },
    { num: 1, date: '1/13/2018' },
    { num: 3, date: '1/16/2018' },
    { num: 4, date: '1/16/2018' }
]


function bineObj(data) {
    let validator= new Set();
    let binedArr = [];
    let numCount = 0;
    
    // Create a list of unique properties to match against:
    data.forEach((e) => validator.add(e.date));

    // For each value in the validator, create a new object in a new array 
    // and add the unique values from the validator to the respective property:
    validator.forEach((e) => {
        binedArr.push({
            num: 0,
            date: e
        });
    })

    // Lastly, for each object in the binedArr, use a counter to sum up the total values of each property
    // as you loop through your data:
    binedArr.forEach((e) => {
        numCount = 0;
        data.forEach((ee) => {
            if (e.date === ee.date) {
                numCount += ee.num;
                e.num = numCount;
            }
        })
    })

    return binedArr;
}

Returns:

[
  { num: 11, date: '1/12/2017' },
  { num: 1, date: '1/13/2018' },
  { num: 7, date: '1/16/2018' }
]
发布评论

评论列表(0)

  1. 暂无评论