2017-04-12 72 views
2

我正在处理一个对象数组。每个对象都有两个属性,大小和数量。Javascript:比较数组元素的属性,如果相同,组合

var drives = [ 
{size:"900GB", count:3}, 
{size:"900GB", count:100}, 
{size:"1200GB", count:5}, 
{size:"900GB", count:1} 
] 

我不喜欢相同的大小如何产生多次,并想将所有重复的大小成仅有1数组索引。

首先我有按大小排序的数组。然后我试着做一个for-loop来管理重复。

drives.sort(function(obj1, obj2) { 
var First = parseInt(obj1.size) 
var Second = parseInt(obj2.size) 
// Ascending: first size less than the previous 
return First - Second; 
}) 


for(var i = 0; i < drives.length-1; i++) 
{ 

    if(drives[i].size == drives[i+1].size) 
    { 
     drives[i+1].count+=drives[i].count; 
     //add the count of the first index to the second index's count 
     drives.splice(i, 1); 
     //delete the first index 
    } 
}   

https://jsbin.com/zayofiqoke/edit?js,console

的环路,似乎并不正确地迭代。它只结合了两个索引。我如何实现我在找的东西?谢谢!

回答

0

编辑:使用Array#filter可能会更短。通过Nina Scholz发布使用此策略的第一个答案。我正在使用filter函数的第二个参数,该函数将this设置为传递回调的上下文,以尽可能少地使用额外的行。

var drives = [ 
 
    {size:"900GB", count:3}, 
 
    {size:"900GB", count:100}, 
 
    {size:"1200GB", count:5}, 
 
    {size:"900GB", count:1} 
 
] 
 

 
var result = drives.filter(function (e) { 
 
    if (e.size in this) this[e.size].count += e.count 
 
    else return this[e.size] = e 
 
}, {}) 
 

 
console.log(result)


原文:一个更好的办法可能是使用 Array#mapArray#reduce

var drives = [ 
 
    {size:"900GB", count:3}, 
 
    {size:"900GB", count:100}, 
 
    {size:"1200GB", count:5}, 
 
    {size:"900GB", count:1} 
 
] 
 

 
var map = drives.reduce(function (map, e) { 
 
    if (e.size in map) map[e.size].count += e.count 
 
    else map[e.size] = e 
 
    return map 
 
}, {}) 
 

 
var result = Object.keys(map).map(function (k) { 
 
    return this[k] 
 
}, map) 
 

 
console.log(result)

+0

伟大的编辑旋转! – wajeezy

0

您可以过滤数组并使用哈希表上的闭包来更新相同大小的项目。

var drives = [{ size: "900GB", count: 3 }, { size: "900GB", count: 100 }, { size: "1200GB", count: 5 }, { size: "900GB", count: 1 }]; 
 

 
drives = drives.filter(function (hash) { 
 
    return function (a) { 
 
     if (!hash[a.size]) { 
 
      hash[a.size] = a; 
 
      return true; 
 
     } 
 
     hash[a.size].count += a.count; 
 
    }; 
 
}(Object.create(null))); 
 

 
console.log(drives);

+0

谢谢龚如心!这是一个非常好的解决方案。 – wajeezy

0

这可能不是最好的实现,但你可以始终保持元素的临时列表,并遍历它:

var tmp = {}; 
var out = []; 
for(var i = 0; i < drives.length; i++) { 
    if(!tmp[JSON.stringify(drives[i])]) { 
     out.push(drives[i]); 
     tmp[JSON.stringify(drives[i])] = true; 
    } 
} 

我做的是迭代通过数组,我将对象转换为JSON并将它用作对象中的键,所以如果有任何相同的对象,它们将被希望捕获,因为它们存在于临时对象中(不断查找〜O(1)stringify会迭代以上循环中的键)。

如果尚未定义密钥,请将该对象推送到新数组并继续到原始数组的末尾。

因此,您的最终解决方案运行在O(n),但它不是非常有效的内存。