【问题标题】:How do I union/merge two Collections by their 'id' using UnderscoreJS如何使用 UnderscoreJS 通过它们的“id”联合/合并两个集合
【发布时间】:2013-05-08 05:54:57
【问题描述】:

我有两个集合(菜单和订单)

菜单集合包含 Item 对象数组

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

并且Orders集合还包含Item对象数组

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

我希望它们通过 ID 将它们的属性合并到另一个集合中(这仅用于模板目的):

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

是否有下划线方法或者我需要为此定义一个函数? [似乎我在下划线上尝试了所有合并功能,但没有一个按我预期的方式工作]

【问题讨论】:

    标签: javascript backbone.js underscore.js javascript-objects


    【解决方案1】:

    不要认为 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);
    

    【讨论】:

    • 您也可以使用 _.findWhere() 方法及其回调简写:_.findWhere(orders, {id: menu.id});
    【解决方案2】:

    假设您的收藏是 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/一起玩的小提琴

    【讨论】:

    • 是的,谢谢,它还包括通过 _.extend 的订单集合的其他属性
    【解决方案3】:

    这应该可以完成工作:

    var result = [];
    _.each(menu, function(el){
        _.extend(el,_.where(orders, {id: el.id})[0] || {});
        result.push(el);
    });
    

    【讨论】:

    • 优秀。我使用它来将一组获取的结果与来自第二个 HTTP 请求(承诺 FTW)的装饰数据合并。谢谢@mamoo!
    【解决方案4】:

    如果是你想做的union,可以用下划线的方式来做:

    // 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/

    【讨论】:

      【解决方案5】:

      我们可以像这样与普通 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;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多