Как объединить/объединить две коллекции по их идентификатору с помощью UnderscoreJS

У меня две коллекции (Меню и Заказы)

Коллекция меню содержит массив объектов Item.

[{'id': '1', 'name': 'apple'}, {'id': '2', 'name': 'orange'}]

И коллекция Orders также содержит массив объектов Item.

[{'id': '1', 'quantity': '0'}]

И я хочу, чтобы они объединили свои атрибуты по идентификатору в другую коллекцию (это необходимо только для целей шаблона):

[{'id': '1', 'name': 'apple', 'quantity': '1'}, {'id': '2', 'name': 'orange'}]

Есть ли для этого метод подчеркивания или мне нужно определить для этого функцию? [Кажется, я перепробовал все функции слияния с символом подчеркивания, но ни одна из них не работает так, как я ожидал]


person user1076813    schedule 08.05.2013    source источник


Ответы (5)


Предполагая, что ваши коллекции являются коллекциями Backbone

var menus = new Backbone.Collection([
    {'id': '1', 'name': 'apple'}, 
    {'id': '2', 'name': 'orange'}
]);

var orders = new Backbone.Collection([{'id': '1', 'quantity': 1}]);

вы можете воспользоваться функциями проксирования коллекций и collection.get :

var merged = menus.map(function(menu) {
    var id = menu.get('id'),
        order = orders.get(id);

    if (!order) return menu.toJSON();

    return _.extend(menu.toJSON(), order.toJSON());
});

И скрипт для игры с http://jsfiddle.net/bs6jN/

person nikoshr    schedule 08.05.2013
comment
да, спасибо за это, он также включает в себя другие атрибуты коллекции заказов через _.extend - person user1076813; 08.05.2013

Не думайте, что для этого определена функция в underscore.js, но один из способов сделать это — использовать _.map и _.find работает следующим образом:

var menus = [{'id': '1', 'name': 'apple'}, {'id': '2', 'name': 'orange'}];

var orders = [{'id': '1', 'quantity': '0'}];

var newMenu = _.map(menus, function (menu) {  
    var order = _.find(orders, function (o) { 
        return o.id == menu.id;
    }); 
    return _.extend(menu, order); 
});

console.log(newMenu);
person naiquevin    schedule 08.05.2013
comment
Также вы можете использовать метод _.findWhere() с сокращением его обратного вызова: _.findWhere(orders, {id: menu.id}); - person JuliaCesar; 08.05.2013

Это должно сделать работу:

var result = [];
_.each(menu, function(el){
    _.extend(el,_.where(orders, {id: el.id})[0] || {});
    result.push(el);
});
person mamoo    schedule 08.05.2013
comment
Превосходно. Я использовал это, чтобы объединить массив полученных результатов с данными оформления из второго HTTP-запроса (обещает FTW). Спасибо @mamoo! - person RoboBear; 29.09.2018

Если вы хотите создать союз, вы можете сделать это с помощью подчеркивания:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

Это просто улучшение исходной функции _.union(*arrays), добавляющее итерацию в рабочую коллекцию (массив объектов).

Вот как это использовать:

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

Исходная функция, которая просто работает с массивом, выглядит так:

_.union = function() {
  return _.uniq(flatten(arguments, true, true));
};

И в бонусе полный пример:

// collectionUnion(*arrays, iteratee)
function collectionUnion() {
    var args = Array.prototype.slice.call(arguments);
    var it = args.pop();

    return _.uniq(_.flatten(args, true), it);
}

var a = [{id: 0}, {id: 1}, {id: 2}];
var b = [{id: 2}, {id: 3}];
var c = [{id: 0}, {id: 1}, {id: 2}];

var result = collectionUnion(a, b, c, function (item) {
    return item.id;
});

console.log(result); // [ { id: 0 }, { id: 1 }, { id: 2 }, { id: 3 } ]

РЕДАКТИРОВАТЬ: я написал сообщение в блоге, если вам нужны подробности: http://geekcoder.org/union-of-two-collections-using-underscorejs/

person Arnaud Valensi    schedule 26.06.2015

Мы можем объединиться с простым js, как это

    var arrOne = [{'id': '1', 'name': 'apple'}, {'id': '2', 'name': 'orange'}];
    var arrTwo = [{'id': '1','quantity': '0'}];

    function mergeArr(arrOne, arrTwo) {
        var mergedArr = [];
        arrOne.forEach(function (item) {
            var O = item;
            arrTwo.forEach(function (itemTwo) {
                if (O.id === itemTwo.id) {
                    O.quantity = itemTwo.quantity;

                }
            });
            mergedArr.push(O);

        });

        return mergedArr;
    }
person Sarath    schedule 08.05.2013