2015-05-21 4 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

Вот еще одна версия vanilla 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

Существует множественный способ сделать, но, как вы хотите, чтобы проверить уникальность, проще всего было бы использовать временную карту, индексированную ваши идентификаторы, на котором вы можете накапливать значения других свойств.

Когда накопление сделано, преобразуйте карту в прямой массив, et voila.

Вы бы сделали это так:

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]; }) 
Смежные вопросы