2015-05-21 154 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]; })