2015-09-30 2 views
1

После выполнения нескольких underscore.js операций (_.map, _.each, _.pluck и _.flatten), у меня есть массив объектов, выглядит следующим образом:Слияние массивов с underscore.js

var userArray = [ 
    {id: 123456, username: "bill123", group: "ONE"}, 
    {id: 123457, username: "joe123", group: "TWO"}, 
    {id: 123457, username: "joe123", group: "TWO"}, 
    {id: 123458, username: "jim123", group: "ONE"} 
] 

Мне нужно создать новый массив с удаленными дубликатами и подсчет количества раз, когда объект появился в массиве. Я могу получить желаемые результаты с двумя отдельными функциями underscore.js, но у меня возникли проблемы с объединением двух результатов.

Рабочими функции заключаются в следующем:

var uniqUsers = _.uniq(taggedUsers, false, function(user) { 
    return user.id 
}); 
    //returns array of unique objects in the same format as above 
    //[{id: 123457, username: "joe123", group: "TWO"},...] 

var userCounts = _.countBy(taggedUsers, "id"); 
    //returns the count for each user in the userArray in a single object 
    //{123456: 1, 123457: 2, 123458: 1} 


Что наилучший подход для возвращения массива объектов, как это:

{id: 123457, username: "joe123", group: "TWO", count: 2} 

Могу ли я добавить дополнительные поля в _.countBy функция? Или мне нужно что-то сделать с _.map?

Любая помощь была бы принята с благодарностью! Благодаря

+0

Также будет плюсом, если массив отсортирован по количеству! – pingo

ответ

4

Вы можете использовать map на userCounts, чтобы создать новый массив, который затем можно сортировать.

var userArray = [ 
    {id: 123456, username: "bill123", group: "ONE"}, 
    {id: 123457, username: "joe123", group: "TWO"}, 
    {id: 123457, username: "joe123", group: "TWO"}, 
    {id: 123458, username: "jim123", group: "ONE"} 
]; 

var userCounts = _.countBy(userArray, "id"); 

var result = _.sortBy(_.map(userCounts, function(count, id) { 
    var user = _.findWhere(userArray, {id: Number(id)}); 
    return _.extend({}, user, {count: count}); 
}), 'count'); 

console.log(result); 

Результат:

[[object Object] { 
    count: 1, 
    group: "ONE", 
    id: 123456, 
    username: "bill123" 
}, [object Object] { 
    count: 1, 
    group: "ONE", 
    id: 123458, 
    username: "jim123" 
}, [object Object] { 
    count: 2, 
    group: "TWO", 
    id: 123457, 
    username: "joe123" 
}] 

JSBin

+2

Обратите внимание, что это будет мутировать исходные объекты в 'userArray'. Если это нежелательно, измените 'return _.extend (user, {count: count});' to 'return _.extend ({}, user, {count: count});'. – GregL

+0

Хорошо, я отредактирую, так как я не собирался менять исходный набор. –

+0

Спасибо @AnidMonsur, это решение работает (извините за задержку ответа). Посмотрев на редактирование, в чем разница между включением/исключением '{}' в функции '_.extend'? @GregL – pingo

3

Я бы просто сделать это в двух _.each с:

var uniquedUsersWithCount = [], 
    userIDToCount = {}; 

_.each(taggedUsers, function (user) { 
    if (userIDToCount[user.id] !== undefined) { 
    userIDToCount[user.id] += 1; 
    } else { 
    userIDToCount[user.id] = 0; 
    uniquedUsersWithCount.push(user); 
    } 
}); 

_.each(uniquedUsersWithCount, function (user) { 
    var count = userIDToCount[user.id]; 
    if (count !== undefined) { 
    user.count = count; 
    } 
}); 
+2

Это не использует полную мощность Underscore, но, вероятно, это более понятный код, который легче читать. – GregL

+0

Спасибо, что это круто, если я правильно понимаю, вы создаете пустой массив, нажимая на него новых пользователей с числом 1, но если пользователь уже существует, добавьте 1 в поле count? – pingo

+0

Но что делает вторая функция '_each'? Немного смущает это @Vinay – pingo

Смежные вопросы