2015-05-21 118 views
2

我想结合一个对象数组,同时删除基于特定值的重复项,在这种情况下它是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或下划线/ lodash。任何建议将不胜感激。

+3

你如何获得的值呈现在你的“myDesiredArray”完成? – DTing

+0

http://stackoverflow.com/questions/7146217/merge-2-arrays-of-objects –

+0

@ DTing,感谢您的发现。我纠正了我的帖子。 – abyrne85

回答

2
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 
0

纯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]); 
} 
0

这里是另一个使用功能方法的香草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; 
}); 
3

使用下划线,这里有一个办法做到这一点

定义sum功能

function sum(numbers) { 
    return _.reduce(numbers, function(result, current) { 
     return result + parseFloat(current); 
    }, 0); 
} 

然后GROUPBY超过id和采摘需要的值,并应用总和超过他们。

_.chain(myArray) 
    .groupBy("id") 
    .map(function(value, key) { 
     return { 
      id: key, 
      rendering : sum(_.pluck(value, "rendering")), 
      completed: sum(_.pluck(value, "completed")) 
     } 
    }) 
    .value(); 
0

解决方案以较少的循环可能

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; 
} 
1

有多种办法的事,但你要检查的唯一性,最简单的方法是使用一个临时的地图,通过你的IDS索引,您可以在其上累积其他属性的值。

当累加完成后,将Map转换为直线阵列,即et瞧

你会做它像这样:

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]; })