开发者问题收集

过滤数组并创建新数组

2017-06-19
106

我有一个非常简单的需求,即从较大的数组中筛选一些对象并创建一个子数组。目前,我正在按如下方式执行,但我想知道我是否可以内联执行并避免 for-each。

        var branches = $filter('filter')(vm.locations, { 'fkLocationTypeId': 5 });
        vm.branchList = [];
        angular.forEach(branches, function (obj) {
            vm.branchList.push({ id: obj.Id,  label: obj.locationDisplayName });
        });
2个回答

由于您既想过滤数组又想修改保留的项目,因此可以将 filter()map() 结合使用,这两种方法都是原生数组方法

vm.branchList = vm.locations
  .filter(function(location) {
    return location.fkLocationTypeId === 5;
  })
  .map(function(location) {
    return {
      id: location.Id,
      label: location.locationDisplayName
    };
  });

如果要避免对数组进行两次迭代,可以使用 reduce() 方法同时执行过滤和映射

vm.branchList = vm.locations
  .reduce(function(builtList, location) {
    if (location.fkLocationTypeId === 5) {
      return builtList.concat({
        id: location.Id,
        label: location.locationDisplayName
      });
    }
    return builtList;
  }, []);
Lennholm
2017-06-19

我认为您使用 forEach 并没有什么大问题,但您可以用对已筛选集执行 map 操作来替换它。

就我个人而言,我会使用 reduce 在一个循环中结合 filtermap 操作,但您可能只会在筛选非常大的数据集时才会开始看到性能提升。

要将两者结合在一个 Reducer 中:

const locToObj = loc => 
  ({ id: loc.Id,  label: loc.locationDisplayName });
 
const branchReducer = (acc, loc) =>
  loc.fkLocationTypeId === 5
    ? (acc.push(locToObj(loc)), acc)
    : acc
 
const branches = vm.locations.reduce(branchReducer, []);
    
user3297291
2017-06-19