如何以更有效的方式组合_.map和_.filter?

时间:2017-01-15 09:12:01

标签: javascript angularjs lodash

我在Angular项目中使用Lodash,我想知道是否有更好的方法来编写以下代码:

$scope.new_arr = _.map(arr1, function(item){
    return _.assign(item, {new_id: _.find(arr2, {id: item.id})});
  });
$scope.new_arr = _.filter($scope.new_arr, function (item) {
  return item.new_id !== undefined;
});

我正在尝试将一个数组中的值与其他数组中的相同对象组合在一起,我想忽略两个数组中没有出现的对象(它类似于sql语言中的join或left outer join)。

以下是此代码示例的小提琴:Click me!

4 个答案:

答案 0 :(得分:9)

我认为最好使用链接

sscanf()

答案 1 :(得分:2)

https://jsfiddle.net/3xjdqsjs/6/

试试这个:

  $scope.getItemById = (array, id) => {
    return array.find(item => item.id == id);
  };

  $scope.mergeArrays = () => {
   let items_with_ids = arr1.filter(item => !_.isNil($scope.getItemById(arr2,item.id)));
   return items_with_ids.map(item => _.assign(item, {new_id: $scope.getItemById(arr2,item.id)}));
  };

答案 2 :(得分:2)

这里提供的答案都是O(n ^ 2)的运行时,因为它们首先在第一个数组上运行外部循环,在第二个数组上运行内部循环。您可以在O(n)中运行它。首先,在单个循环中创建arr2中所有id的hashmap;这将允许我们进行订单1查询。在arr1的第二个循环中,检查此hashmap以确定这些项是否与O(n)一起存在。总复杂度为n + n = 2n,仅为O(n)。

// provision some test arrays
var arr1 = [
    {
        id: 2
    },
    {
        id: 4
    },
    {
        id: 6
    }
]

var arr2 = [
    {
        id: 3
    },
    {
        id: 4
    },
    {
        id: 5
    },
    {
        id: 6
    }
]

// First, we create a map of the ids of arr2 with the items. Complexity: O(n)
var mapIdsToArr2Items = _.reduce(arr2, function(accumulator, item) {
    accumulator[item.id] = item;
    return accumulator;
}, {});

// Next, we use reduce (instead of a _.map followed by a _.filter for slightly more performance.
// This is because with reduce, we loop once, whereas with map and filter, 
// we loop twice). Complexity: O(n)
var combinedArr = _.reduce(arr1, function(accumulator, item) {

    // Complexity: O(1)
    if (mapIdsToArr2Items[item.id]) {
        // There's a match/intersection! Arr1's item matches an item in arr 2. Include it
        accumulator.push(item);
    }
    return accumulator;    
}, []);

console.log(combinedArr)

答案 3 :(得分:0)

您可以先使用arr1制作Map,然后将arr2的项目与arr1的属性进行映射。

var arr1 = [{ id: 1, title: 'z' }, { id: 2, title: 'y' }, { id: 3, title: 'x' }, { id: 4, title: 'w' }, { id: 5, title: 'v' }],
    arr2 = [{ id: 2, name: 'b' }, { id: 3, name: 'c' }, { id: 4, name: 'd' }, { id: 5, name: 'e' }],
    map = new Map(arr1.map(a => [a.id, a])),
    result = arr2.map(a => Object.assign({}, a, map.get(a.id)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }