合并数组并组合值
Merge arrays and combine the values
我正在尝试组合对象数组,同时根据特定值删除重复项,在本例中为 id
。我想合并每个对象中的其他属性。
这是我的:
var myArray = [
{
id : 1,
rendering : 0,
completed : 1
},
{
id : 2,
rendering : 0,
completed : 1
},
{
id : 3,
rendering : 0,
completed : 1
},
{
id : 1,
rendering : 1,
completed : 0
},
{
id : 2,
rendering : 1,
completed : 0
},
{
id : 3,
rendering : 1,
completed : 0
},
]
这就是我想要的:
var myDesiredArray = [
{
id : 1,
rendering: 1,
completed: 1
},
{
id : 2,
rendering: 1,
completed: 1
},
{
id : 3,
rendering: 1,
completed: 1
},
]
我很乐意直接 javascript 或 underscore/lodash。任何建议将不胜感激。
纯JS解决方案
首先要做的是使用地图进行快速查找:
var map = {};
myArray.forEach(function(item){
var mapItem = map[item.id] || {
id : item.id,
rendering : 0,
completed : 0
}
mapItem.rendering += item.rendering;
mapItem.completed += item.completed;
map[item.id] = mapItem;
});
然后您可以将地图转换回数组:
var myDesiredArray = [];
for (var id in map) {
myDesiredArray.push(map[id]);
}
这是另一个使用函数式方法的 vanilla js 版本:
myArray.reduce(function(prev, cur) {
if (prev[cur.id]) {
prev[cur.id].rendering += cur.rendering;
prev[cur.id].completed += cur.completed;
} else {
prev[cur.id] = cur;
}
return prev;
}, []).filter(function(val) {
return val;
});
function merge(arr) {
var uniqItems = arr.reduce(function(memo, item) {
if (!memo[item.id]) {
memo[item.id] = item;
} else {
Object.keys(item).forEach(function(k) {
if (item[k]) { memo[item.id][k] = item[k]; }
});
}
return memo;
}, {});
return Object.keys(uniqItems).map(function(k) {
return uniqItems[k];
});
}
merge(myArray); // => myDesiredArray
使用下划线,这是一种方法
定义一个sum
函数
function sum(numbers) {
return _.reduce(numbers, function(result, current) {
return result + parseFloat(current);
}, 0);
}
然后对 id
进行分组并提取所需的值并对它们求和。
_.chain(myArray )
.groupBy("id")
.map(function(value, key) {
return {
id: key,
rendering : sum(_.pluck(value, "rendering")),
completed: sum(_.pluck(value, "completed"))
}
})
.value();
可能有更少循环的解决方案
function myMerge(myArray) {
var temp = {},
myDesiredArray = [];
for (var i = 0; i < myArray.length; ++i) {
var elem = myArray[i];
if (!temp[elem.id]) {
temp[elem.id] = {
'id': elem.id,
'rendering': elem.rendering,
'completed': elem.completed,
};
myDesiredArray.push(temp[elem.id])
}
temp[elem.id].rendering += elem.rendering;
temp[elem.id].completed += elem.completed;
}
return myDesiredArray;
}
有多种方法可以做到,但如果您想检查唯一性,最简单的方法是使用临时地图,由您的 ID 索引,您可以在其上累积其他属性的值。
累加完成后,将Map转换为直线数组,瞧瞧。
你会这样做:
var array; // defined elsewhere
var tmp = {}; // temporary map
// accumulate the properties in the map
array.forEach(function(elt) {
if (tmp[elt.id] == null)
tmp[elt.id] = elt
else {
tmp[elt.id].prop += elt.prop;
// (...) do the accumulation here
}
});
// then convert this map to an array by iterating on the ids
Object.keys(tmp).map(function(id) { return tmp[id]; })
我正在尝试组合对象数组,同时根据特定值删除重复项,在本例中为 id
。我想合并每个对象中的其他属性。
这是我的:
var myArray = [
{
id : 1,
rendering : 0,
completed : 1
},
{
id : 2,
rendering : 0,
completed : 1
},
{
id : 3,
rendering : 0,
completed : 1
},
{
id : 1,
rendering : 1,
completed : 0
},
{
id : 2,
rendering : 1,
completed : 0
},
{
id : 3,
rendering : 1,
completed : 0
},
]
这就是我想要的:
var myDesiredArray = [
{
id : 1,
rendering: 1,
completed: 1
},
{
id : 2,
rendering: 1,
completed: 1
},
{
id : 3,
rendering: 1,
completed: 1
},
]
我很乐意直接 javascript 或 underscore/lodash。任何建议将不胜感激。
纯JS解决方案
首先要做的是使用地图进行快速查找:
var map = {};
myArray.forEach(function(item){
var mapItem = map[item.id] || {
id : item.id,
rendering : 0,
completed : 0
}
mapItem.rendering += item.rendering;
mapItem.completed += item.completed;
map[item.id] = mapItem;
});
然后您可以将地图转换回数组:
var myDesiredArray = [];
for (var id in map) {
myDesiredArray.push(map[id]);
}
这是另一个使用函数式方法的 vanilla js 版本:
myArray.reduce(function(prev, cur) {
if (prev[cur.id]) {
prev[cur.id].rendering += cur.rendering;
prev[cur.id].completed += cur.completed;
} else {
prev[cur.id] = cur;
}
return prev;
}, []).filter(function(val) {
return val;
});
function merge(arr) {
var uniqItems = arr.reduce(function(memo, item) {
if (!memo[item.id]) {
memo[item.id] = item;
} else {
Object.keys(item).forEach(function(k) {
if (item[k]) { memo[item.id][k] = item[k]; }
});
}
return memo;
}, {});
return Object.keys(uniqItems).map(function(k) {
return uniqItems[k];
});
}
merge(myArray); // => myDesiredArray
使用下划线,这是一种方法
定义一个sum
函数
function sum(numbers) {
return _.reduce(numbers, function(result, current) {
return result + parseFloat(current);
}, 0);
}
然后对 id
进行分组并提取所需的值并对它们求和。
_.chain(myArray )
.groupBy("id")
.map(function(value, key) {
return {
id: key,
rendering : sum(_.pluck(value, "rendering")),
completed: sum(_.pluck(value, "completed"))
}
})
.value();
可能有更少循环的解决方案
function myMerge(myArray) {
var temp = {},
myDesiredArray = [];
for (var i = 0; i < myArray.length; ++i) {
var elem = myArray[i];
if (!temp[elem.id]) {
temp[elem.id] = {
'id': elem.id,
'rendering': elem.rendering,
'completed': elem.completed,
};
myDesiredArray.push(temp[elem.id])
}
temp[elem.id].rendering += elem.rendering;
temp[elem.id].completed += elem.completed;
}
return myDesiredArray;
}
有多种方法可以做到,但如果您想检查唯一性,最简单的方法是使用临时地图,由您的 ID 索引,您可以在其上累积其他属性的值。
累加完成后,将Map转换为直线数组,瞧瞧。
你会这样做:
var array; // defined elsewhere
var tmp = {}; // temporary map
// accumulate the properties in the map
array.forEach(function(elt) {
if (tmp[elt.id] == null)
tmp[elt.id] = elt
else {
tmp[elt.id].prop += elt.prop;
// (...) do the accumulation here
}
});
// then convert this map to an array by iterating on the ids
Object.keys(tmp).map(function(id) { return tmp[id]; })