Javascript:比较数组元素属性,如果相同,则组合

时间:2017-04-12 17:57:21

标签: javascript arrays

我正在处理一系列对象。每个对象都有两个属性,大小和数量。

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

我不喜欢同样大小的多次出现,并希望将所有重复的大小合并到一个数组索引中。

首先,我按大小排序数组。然后我尝试制作一个for循环来管理重复。

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

for循环似乎没有正确迭代。它只结合了两个索引。我如何实现我正在寻找的东西?谢谢!

3 个答案:

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

答案 1 :(得分: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)中运行,但它的内存效率并不高。

答案 2 :(得分:0)

修改:使用Array#filter可能会更短。感谢Nina Scholz使用此策略发布第一个答案。我正在使用filter函数的第二个参数,它设置给传递的回调的this上下文,使用尽可能少的额外行。

&#13;
&#13;
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)
&#13;
&#13;
&#13;

<小时/> 原文:更好的方法可能是使用Array#mapArray#reduce

&#13;
&#13;
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)
&#13;
&#13;
&#13;