如何使用javascript数组对象,例如:
my objArr = [
{key:Mon Sep 23 2013 00:00:00 GMT-0400, val:42},
{key:Mon Sep 24 2013 00:00:00 GMT-0400, val:78},
{key:Mon Sep 25 2013 00:00:00 GMT-0400, val:23},
{key:Mon Sep 23 2013 00:00:00 GMT-0400, val:54}]
并通过对值进行求和来合并重复键。 为了得到这样的东西:
my reducedObjArr = [
{key:Mon Sep 23 2013 00:00:00 GMT-0400, val:96},
{key:Mon Sep 24 2013 00:00:00 GMT-0400, val:78},
{key:Mon Sep 25 2013 00:00:00 GMT-0400, val:23}]
我已尝试迭代并添加到新数组,但这不起作用:
var reducedObjArr = [];
var item = null, key = null;
for(var i=0; i<objArr.length; i++) {
item=objArr[i];
key = Object.keys(item)[0];
item=item[key];
if(!result[key]){
result[key] = item;
}else{
result[key] += item;}
}a
答案 0 :(得分:11)
您应该使用.key
属性将未找到的每个对象分配给结果。
如果找到,则需要添加.val
。
var temp = {};
var obj = null;
for(var i=0; i < objArr.length; i++) {
obj=objArr[i];
if(!temp[obj.key]) {
temp[obj.key] = obj;
} else {
temp[obj.key].val += obj.val;
}
}
var result = [];
for (var prop in temp)
result.push(temp[prop]);
此外,部分问题是您重复使用item
变量来引用.key
的值,因此您丢失了对该对象的引用。
答案 1 :(得分:6)
答案 2 :(得分:5)
您可以使用哈希表进行key
分组。
var array = [{ key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 42 }, { key: 'Mon Sep 24 2013 00:00:00 GMT-0400', val: 78 }, { key: 'Mon Sep 25 2013 00:00:00 GMT-0400', val: 23 }, { key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 54}],
grouped = [];
array.forEach(function (o) {
if (!this[o.key]) {
this[o.key] = { key: o.key, val: 0 };
grouped.push(this[o.key]);
}
this[o.key].val += o.val;
}, Object.create(null));
console.log(grouped);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
另一种方法是收集Map
中的所有键/值对,并使用Array.from
格式化最终数组并对对象进行回调。
var array = [{ key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 42 }, { key: 'Mon Sep 24 2013 00:00:00 GMT-0400', val: 78 }, { key: 'Mon Sep 25 2013 00:00:00 GMT-0400', val: 23 }, { key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 54 }],
grouped = Array.from(
array.reduce((m, { key, val }) => m.set(key, (m.get(key) || 0) + val), new Map),
([key, val]) => ({ key, val })
);
console.log(grouped);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 3 :(得分:4)
var targetObj = {};
for (var i = 0; i < objArr.length; i++) {
if (!targetObj.hasOwnProperty(objArr[i].key)) {
targetObj[objArr[i].key] = 0;
}
targetObj[objArr[i].key] += objArr[i].val;
}
答案 4 :(得分:1)
尝试一下,应该有帮助
var arr1 = [
{ name: 'besart', value: 12 },
{ name: 'astrit', value: 10 },
{ name: 'astrit', value: 10 },
{ name: 'besar', value: 18 },
{ name: 'besar', value: 3 },
{ name: 'astrit', value: 3 },
{ name: 'besart', value: 3 },
{ name: 'besart', value: 10 },
{ name: 'besar', value: 0 },
];
var arr2 = [];
var emri = "";
var value = 0;
for(var i = 0;i<arr1.length;i++){
emri=arr1[0].name;
value+=arr1[0].value;
for(var j=1;j<arr1.length;j++){
if(emri==arr1[j].name){
value+=arr1[j].value;
arr1.splice(j,1);
j--;
}
}
arr1.splice(0,1);
arr2[i] = {name:emri,value:value};
value=0;
}
console.log(arr2);
以下是仅使用一个循环(while循环)的另一种解决方案:
var arr2 = [];
var emri = "";
var value = 0;
var i=1;
var j=0;
while(arr1.length != 0){
emri = arr1[0].name;
if(emri == arr1[i].name){
value+=arr1[i].value;
arr1.splice(i,1);
i--;
}
i++;
if(i==arr1.length){
value+=arr1[0].value;
i=1;
arr2[j]={name:emri,value:value};
j++;
value=0;
arr1.splice(0,1);
}
}
答案 5 :(得分:1)
比其他地方发布的减少更简单
const objArr = [
{key:"Mon Sep 23 2013 00:00:00 GMT-0400", val:42},
{key:"Mon Sep 24 2013 00:00:00 GMT-0400", val:78},
{key:"Mon Sep 25 2013 00:00:00 GMT-0400", val:23},
{key:"Mon Sep 23 2013 00:00:00 GMT-0400", val:54}];
const output = objArr.reduce((accumulator, cur) => {
let date = cur.key;
let found = accumulator.find(elem => elem.key === date)
if (found) found.val += cur.val;
else accumulator.push(cur);
return accumulator;
}, []);
console.log(output)
答案 6 :(得分:0)
这是您的替代方案,但与Explosion Pills类似,重用原始数组而不是创建新数组或不同对象。这种排序可能没有必要,会使事情变慢一些,但可以将其删除。
的Javascript
function reduceMyObjArr(arr) {
var temp = {},
index;
for (index = arr.length - 1; index >= 0; index -= 1) {
key = arr[index].key;
if (temp.hasOwnProperty(key)) {
arr[temp[key]].val += arr[index].val;
arr.splice(index, 1);
} else {
temp[key] = index;
}
}
arr.sort(function (a, b) {
if (a.key === b.key) {
return 0;
}
if (a.key < b.key) {
return -1;
}
return 1;
});
return arr;
}
var myObjArr = [{
key: "Mon Sep 23 2013 00: 00: 00 GMT - 0400",
val: 42
}, {
key: "Mon Sep 24 2013 00: 00: 00 GMT - 0400",
val: 78
}, {
key: "Mon Sep 25 2013 00: 00: 00 GMT - 0400",
val: 23
}, {
key: "Mon Sep 23 2013 00: 00: 00 GMT - 0400",
val: 54
}];
reduceMyObjArr(myObjArr);
console.log(myObjArr);
和jsperf将此(有和没有排序)与已接受的答案进行比较。您可以通过扩展数据集来改进性能测试。
答案 7 :(得分:0)
你也可以尝试使用javascript linq框架,它与sql语句完全相同,sql语句给出了所需的输出,编写的代码更少,有效,可在linq.js找到
var objArr =
[
{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:42},
{key:'Mon Sep 24 2013 00:00:00 GMT-0400', val:78},
{key:'Mon Sep 25 2013 00:00:00 GMT-0400', val:23},
{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:54}
];
var aggregatedObject = Enumerable.From(objArr)
.GroupBy("$.key", null,
function (key, g) {
return {
key: key,
contributions: g.Sum("$.val")
}
})
.ToArray();
console.log(aggregatedObject);
&#13;
<script src="http://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.min.js"></script>
&#13;
与循环相比,这非常简单。 我希望这可能有所帮助。
答案 8 :(得分:0)
最近,我需要类似的实现,并且使用了某些使用reduce函数的家伙提供的类似解决方案。几天后,我想自己实现类似的东西,结果就是了。
const users = [
{ id: 1, name: 'ernest', spent: 40 },
{ id: 2, name: 'ernest', spent: 40 },
{ id: 3, name: 'astrit', spent: 22 },
{ id: 4, name: 'astrit', spent: 2956 },
{ id: 5, name: 'astrit', spent: 22 },
{ id: 6, name: 'besart', spent: 40 },
{ id: 7, name: 'besart', spent: 100},
{ id: 8, name: 'besart', spent: 4000 }
];
const sum = [];
users.forEach(el => {
if(sum.length === 0){
delete el.id;
sum.push(el);
}
else
{
const get = () => {
for(let i = 0; i < sum.length; i++){
if(sum[i].name === el.name ){
return { stat: true, id: i };
}
}
}
let i = get();
if(i){
sum[i.id].spent += el.spent;
}
else
{
delete el.id;
sum.push(el);
}
}
});
console.log(sum);
输出:
[ { name: 'ernest', spent: 80 }, { name: 'astrit', spent: 3000 }, { name: 'besart', spent: 4140 } ]
答案 9 :(得分:0)
function mergeDuplicatesBy(array, getKey, mergeWith) {
const buff = {}
array.forEach(function (arrayElement) {
const key = getKey(arrayElement)
const alreadyExistingVal = buff[key]
if (alreadyExistingVal) {
buff[key] = mergeWith(alreadyExistingVal, arrayElement)
} else {
buff[key] = arrayElement
}
})
return Object.values(buff)
}
mergeDuplicatesBy(
arr,
x => x.name,
(x, y) => ({ name: x.name, foo: x.foo + y.foo })
)
答案 10 :(得分:0)
可以将 Array#reduce
与对象一起使用来存储每个键的值。
let arr = [{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:42},{key:'Mon Sep 24 2013 00:00:00 GMT-0400', val:78},{key:'Mon Sep 25 2013 00:00:00 GMT-0400', val:23},{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:54}];
let res = Object.values(arr.reduce((acc, curr)=>{
(acc[curr.key] = acc[curr.key] || {key: curr.key, val: 0}).val += curr.val;
return acc;
}, {}));
console.log(res);
在较新的浏览器中,可以使用 logical nullish assignment。
let arr = [{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:42},{key:'Mon Sep 24 2013 00:00:00 GMT-0400', val:78},{key:'Mon Sep 25 2013 00:00:00 GMT-0400', val:23},{key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:54}];
let res = Object.values(arr.reduce((acc, curr)=>{
(acc[curr.key] ??= {key: curr.key, val: 0}).val += curr.val;
return acc;
}, {}));
console.log(res);