0

I am trying to merge JS objects together that have the same key. In this case the key I plan to use is the "time" field, and then for each time I want to include every "app" as a key, and "sum" as its value. The other fields I do not plan to include.

I've tried a few routes but still having trouble, code below:

var data = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

const result = data.reduce(function (r, e) {
    return Object.keys(e).forEach(function (k) {
        if (!r[k]) r[k] = [].concat(e[k])
        else r[k] = r[k].concat(e[k])
    }), r
}, {})

console.log(result)

This is how I want the data to output:


[
    {
        "time": "00:06",
        "cloudmark-desktop": 2970,
        "dns": 519169
    },
    {
        "time": "01:06",
        "cloudmark-desktop": 999,
        "dns": 999
    }
]

Any help appreciated! Thanks

3
  • JSON is a textual notation for data exchange. (More here.) If you're dealing with JavaScript source code, and not dealing with a string, you're not dealing with JSON. Commented Jul 2, 2019 at 12:36
  • What if the time key is equal in many objects? Commented Jul 2, 2019 at 12:41
  • is it not groupBy? check out lodash groupby if that helps. Commented Jul 2, 2019 at 12:51

6 Answers 6

1

You were using {} in reduce method instead of []. Try this snippet for the shortest method to achieve this.

var data = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

const result = data.reduce(function (r, e) {
    let val = r.find(({time}) => time === e.time)
    if (!val) {
        val = {}
        r.push(val)
    }
    val.time = e.time;
    val[e.app] = e.sum;
    return r;
}, []);

console.log(result)

Sign up to request clarification or add additional context in comments.

Comments

1

Here's one way, albeit a bit ugly:

var output = {};
var data   = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

for (var i = 0; i < data.length; i++) {
    var d = data[i];

    if (output[d["time"]]) {
        output[d["time"]][d["app"]] = d["sum"];
    } else {
        output[d["time"]] = {
            time: d["time"],
            [d["app"]]: d["sum"]
        }
    }
}

console.log(Object.values(output));

Comments

1

const data = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

const formattedData = data.reduce((acc, a) => {
  const timeExists = acc.findIndex(b => a.time === b.time);

  if(timeExists > -1) {
    const copy = [...acc];
    copy[timeExists] = {
      ...copy[timeExists],
      [a.app]: a.sum
    }
    return copy
  } else {
    return [
      ...acc,
      {
        time: a.time,
        [a.app]: a.sum	
      }
    ]
  }
}, []);

console.log(formattedData);

Try this. Probably the first part of the if statement deserves some love though.

Comments

1

If you prefer doing it without the help of libraries like lodash you can do it like this:

var data = [
{
    "eventdate": 1561334400000,
    "app": "cloudmark-desktop",
    "sum": 2970,
    "events": "2.9KiB",
    "time": "00:06"
},
{
    "eventdate": 1561334400000,
    "app": "dns",
    "sum": 519169,
    "events": "507.0KiB",
    "time": "00:06"
},
{
    "eventdate": 1561334400000,
    "app": "cloudmark-desktop",
    "sum": 999,
    "events": "507.0KiB",
    "time": "01:06"
},
{
    "eventdate": 1561334400000,
    "app": "dns",
    "sum": 999,
    "events": "507.0KiB",
    "time": "01:06"
}
];

const result = data.reduce((acc, value, key) => {
  const object = acc.find(item => item.time === value.time);

  if(object) {
    if (Number.isInteger(object[value.app])) {
      object[value.app] += value.sum  
    } else {
      object[value.app] = value.sum
    }
    
    return acc;
  }

  acc.push({
    time: value.time,
    [value.app]: value.sum
  });

  return acc;
}, []);

console.log(result);

Comments

1

One of the possible solutions:

const data = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

const groupedDataByTime = data.reduce((accumulator, currentValue) => {
	if (!accumulator.hasOwnProperty(currentValue.time)) {
		accumulator[currentValue.time] = {};
	}
	
	const mapByTime = accumulator[currentValue.time];
	if (!mapByTime.hasOwnProperty(currentValue.app)) {
		mapByTime[currentValue.app] = 0;
	}
	mapByTime[currentValue.app] += parseInt(currentValue.sum, 10);
	
	return accumulator;
}, {});

const result = Object.keys(groupedDataByTime).map(time => {
	return Object.assign({ time }, groupedDataByTime[time]);
});

console.log(result);

2 Comments

Looks like you're concatenating objects: "cloudmark-desktop": "[object Object]2970"
@user7290573 yoг are right, just i misspelled a little. already fixed. thanks a lot.
0

Here is another solution in pure JavaScript which is also more easy to read and understand:

var timesArray = [];
var uniqueTimesArray = [];
var result = [];
var items = [
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 2970,
        "events": "2.9KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 519169,
        "events": "507.0KiB",
        "time": "00:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "cloudmark-desktop",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    },
    {
        "eventdate": 1561334400000,
        "app": "dns",
        "sum": 999,
        "events": "507.0KiB",
        "time": "01:06"
    }
];

function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

items.forEach(function(element) {
  timesArray.push(element.time);
});

uniqueTimesArray = timesArray.filter( onlyUnique );

uniqueTimesArray.forEach(function(timeElement) {
  var resultItem = {};
  var key = "time";
  resultItem[key] = timeElement;
  items.forEach(function(item) {      
      if(item.time == timeElement){
          resultItem[item.app] = item.sum;
      }
  });
  result.push(resultItem);
});

console.log(result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.