将具有相同键,值的JS对象合并到数组中

时间:2019-07-02 12:35:14

标签: javascript arrays node.js

我正在尝试将具有相同键的JS对象合并在一起。在这种情况下,我计划使用的键是“时间”字段,然后每次我都希望将每个“应用程序”都包含为键,并将“总和”包含为其值。我不打算包括的其他字段。

我尝试了一些路线,但仍然遇到问题,代码如下:

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)

这就是我希望数据输出的方式:


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

任何帮助表示赞赏!谢谢

6 个答案:

答案 0 :(得分:1)

这是一种方法,尽管有点难看:

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));

答案 1 :(得分:1)

如果您更喜欢在没有lodash之类的库帮助下进行操作,则可以这样做:

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);

答案 2 :(得分: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);

尝试一下。不过,如果if语句的第一部分值得一提。

答案 3 :(得分:1)

您在化简方法中使用的是{},而不是[]。尝试使用此代码段以最短的方法来实现此目的。

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)

答案 4 :(得分: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 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);

答案 5 :(得分:0)

这是纯JavaScript的另一种解决方案,也更易于阅读和理解:

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);