我有一个对象数组,数组中的两个对象是相同的(最后两个):
[
{
"facilities": 1,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
},
{
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}
]
我想将两个相同的对象组合成一个对象,其中'facilities'键是每个'facility'值的总和:
[
{
"facilities": 2,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
},
{
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
},
{
"facilities": 2,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
},
]
有没有办法在javascript中使用Node或者使用Node的underscore.js?
答案 0 :(得分:3)
普通js的解决方案:
我们会遍历项目数组,并根据指定的键值检查重复项。
当我们遇到我们之前遇到的价值时,这表明我们发现了重复。如果对象是新的,我们存储该事件。如果我们之前已经看过它,我们将合并这两个对象并存储我们的合并表示。
为了能够快速检查我们之前是否看到过相同的物体,我们将使用参考物体。该对象包含每个唯一键的项目。
在这个例子中我定义:
facilities
道具的逻辑
// Take an array of objects, compare them by `key`, merge if the `key`
// is not unique, return a new array.
var mergeDuplicatesByKey = function(items, mergeStrat, key) {
return objValues(items.reduce(function(result, item) {
var id = item[key];
if (!result[id]) {
result[id] = item;
} else {
result[id] = mergeStrat(result[id], item);
}
return result;
}, {}));
};
// Our merge strategy:
// - create a new object
// - add all of item1 and item2's properties
// - sum the facilities prop
var merge = function(item1, item2) {
return Object.assign({}, item1, item2, {
facilities: item1.facilities + item2.facilities
});
};
// The example data:
var data = [{
"facilities": 1,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
}, {
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
}, {
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}, {
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}];
// Call merge method with our own strategy, comparing items by `place`
console.log(mergeDuplicatesByKey(data, merge, "place"));
// Utils:
// Return the values for each key in in an object
function objValues(obj) {
return Object.keys(obj).map(function(key) {
return obj[key];
});
};

答案 1 :(得分:1)
一个选项(需要两次迭代)就是将阵列缩小到一个关键的对象(这样你就可以总结设施)。你可以在那里停下来,只是迭代生成的对象,或者如果你需要它作为求和数组运行Object.keys
并只返回存储在每个键上的对象。
缩小为对象:
var reduced = facilities.reduce(function(p, c) {
if (p[c.place]) p[c.place].facilities++;
else p[c.place] = c;
return p;
}, {});
获取总和值:
Object.keys(reduced).map(function(item) { return reduced[item] });
var facilities = [
{
"facilities": 1,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
},
{
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}
];
var reduced = facilities.reduce((p, c) => {
if (p[c.place]) p[c.place].facilities++;
else p[c.place] = c;
return p;
}, {});
console.log(reduced);
var summedArray = Object.keys(reduced).map(function(item) { return reduced[item];
});
console.log(summedArray);

答案 2 :(得分:1)
首先,根据您所需的情况对复合键进行分组:
var keyDel = '|';
var groups = _.groupBy(list, function(value){
return value.place + keyDel + value.state + keyDel + value.lat + value.lon;
});
然后将每个组成员合并为一个,更新计数:
var data = _.map(groups, function(group){
return {
facilities: group.length,
place: group[0].place,
state: group[0].state,
lat: group[0].lat,
lon: group[0].lon
}
});
答案 3 :(得分:0)
这是我从另一个解决类似问题的堆栈溢出问题中收集的函数。它是在javascript中。
var compare = function (json1, json2) {
var i, l, leftChain, rightChain;
function compare2Objects (x, y) {
var p;
// remember that NaN === NaN returns false
// and isNaN(undefined) returns true
if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
return true;
}
// Compare primitives and functions.
// Check if both arguments link to the same object.
// Especially useful on the step where we compare prototypes
if (x === y) {
return true;
}
// Works in case when functions are created in constructor.
// Comparing dates is a common scenario. Another built-ins?
// We can even handle functions passed across iframes
if ((typeof x === 'function' && typeof y === 'function') ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)) {
return x.toString() === y.toString();
}
// At last checking prototypes as good as we can
if (!(x instanceof Object && y instanceof Object)) {
return false;
}
if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}
if (x.constructor !== y.constructor) {
return false;
}
if (x.prototype !== y.prototype) {
return false;
}
// Check for infinitive linking loops
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}
// Quick checking of one object being a subset of another.
// todo: cache the structure of arguments[0] for performance
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}
}
for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}
switch (typeof (x[p])) {
case 'object':
case 'function':
leftChain.push(x);
rightChain.push(y);
if (!compare2Objects (x[p], y[p])) {
return false;
}
leftChain.pop();
rightChain.pop();
break;
default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}
return true;
}
leftChain = []; //Todo: this can be cached
rightChain = [];
return (!compare2Objects(json1, json2));
}
我用它来比较Backbone模型(取决于underscore.js)
答案 4 :(得分:0)
简单而优雅。如果你愿意,可以更好地改变或评论。我使用了一些es6。
var _ = require('underscore');
// Check if array arr contains object obj
function exists(arr, obj) {
var found = false;
arr.forEach((item) => {
if (_.isMatch(item, obj)) {
found = true;
}
});
return found;
}
var final = [];
original.forEach((obj) => {
if (exists(final, obj)) {
var index = _.findIndex(final, finalObj => _.isMatch(finalObj, obj))
++final[index].facilities
} else {
final.push(obj);
}
});
return final;
答案 5 :(得分:0)
var list = [
{
"facilities": 1,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
},
{
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}
]
var uniqueList = _.uniq(list, function(item) {
return item.toString();
});
/*
uniqueList will be:
{
"facilities": 1,
"place": "Campbellsville",
"state": "KY",
"lat": 37.34595018,
"lon": -85.34544564
},
{
"facilities": 1,
"place": "Lexington",
"state": "KY",
"lat": 38.040584,
"lon": -84.503716
},
{
"facilities": 1,
"place": "Hebron",
"state": "KY",
"lat": 39.066147,
"lon": -84.703189
}
*/
接受回电
{{1}}
如果将项目转换为String,则应该能够检测到重复。
注意: