【问题标题】:Underscore.js _.map function : skip a valueUnderscore.js _.map 函数:跳过一个值
【发布时间】:2015-06-12 13:33:13
【问题描述】:

我正在尝试在对象数组上使用 underscore.js _.map 函数,以获取具有每个对象属性的数组。这是通常的情况,所以:

var finalArray = _.map(myArray, function(obj) {
    return obj.myProperty;
});

但在某些情况下,我需要在数组中添加 nothing。可能是这样的:

var finalArray = _.map(myArray, function(obj) {
    if (!obj.ignore) {
        return obj.myProperty;
    }
});

这样做的结果是一个undefined值被推入数组,这和根本不推任何东西是不一样的。

有没有办法让 map 函数不推送值,或者我是否需要对我的 finalArray 进行后处理以删除不需要的 undefined?

【问题讨论】:

  • 我认为您应该考虑选择 Thomas Eschemann 的最佳答案,因为它只循环一次数组的所有元素,如“有没有办法让 map 函数不推送值",这个问题的主要目标。答案是使用 reduce() 而不是 map()。
  • 当前选择的答案是针对问题的第二部分“我需要对我的 finalArray 进行后处理以删除不需要的未定义的吗?”。第二部分的答案是:不,你不需要后处理 finalArray(),你需要使用 reduce() 而不是 map() 来避免后处理。

标签: javascript underscore.js


【解决方案1】:

你应该在 _.map() 之前使用 _.filter()

var filteredArray = _.filter(myArray,function(obj) {
     return !obj.ignore;
});

var finalArray = _.map(filteredArray, function(obj) {
    return obj.myProperty;
});

【讨论】:

  • 之后,而不是之前
  • 正如 foucdeg 描述他的问题,没有必要转换输入来决定是否应该排除它们。 filter before 那么在性能方面更好
【解决方案2】:

你可以使用reduce:

myArray.reduce(function (acc, obj) {
    if (!obj.ignore) {
        acc.push(obj.myProperty);
    }
    return acc;
}, []);

或者用lodash:

_.reduce(myArray, function (acc, obj) {
  if (!obj.ignore) {
    acc.push(obj.myProperty);
  }
  return acc;
}, []);

【讨论】:

  • 我认为这是最好的答案,因为它只循环一次所有元素,正如@foucdeg“有没有办法让地图函数不推送值”。答案是使用 reduce() 而不是 map()。
  • 同意这应该是公认的答案 - 只循环一次。另请注意,这适用于underscorejs,不知道为什么在这里提到lodash,因为OP 询问underscorejs。 underscore 的文档也有点令人困惑:“reduce 将值列表归结为单个值。”在这种情况下,单个值是一个数组...
【解决方案3】:

这可以单独使用下划线方法来完成,points-free style:

var finalArray = _.chain(myArray)
    .reject('ignore')
    .pluck('myProperty')
    .value();

【讨论】:

  • 我喜欢这种方法。它很干净而且非常易读。 (也纯函数式、单子思维)
  • @Pavlo 你需要一个带有下划线的显式.chain,你可以简单地使用.reject('ignore')而不是.reject(_.property('ignore'))。 jsfiddle.net/nikoshr/2gpvws1u
【解决方案4】:

.map 将映射出一个新值到数组中,您可以使用.filter 来过滤数组。仅供参考,您可以使用 .pluck 从对象映射属性:

_.chain(myArray).filter(function(obj) { return !obj.ignore; }).pluck('myProperty').value();

你也可以像这样使用.where:

_.chain(myArray).where({ignore: false}).pluck('myProperty').value();

或者:

_.pluck(_.where(myArray, {ignore: false}), 'myProperty');

【讨论】:

    【解决方案5】:

    尝试使用 lodash 的 compact()。它创建一个删除所有虚假值的数组。因此,false、null、0、""、undefined 和 NaN 的值被删除。

    https://lodash.com/docs#compact

    我正在使用它——它非常干净。

    【讨论】:

      【解决方案6】:

      所以这意味着你想要过滤,然后映射你的数组。

      要以underscore 方式执行此操作,您需要将数组传递到此管道中:

      myArray --> filter --> ma​​p --> finalArray

      var isIncluded = function(obj){
          return !obj.ignore
      }
      var takeProperty = function(obj){
          return obj.myProperty
      }
      var finalArray = _.map( _.filter(myArray, isIncluded), takeProperty  );
      

      【讨论】:

      • 注意您可以将 takeProperty 替换为 _.pluck 函数,就像另一个答案中建议的 @dev-null 一样。
      • @foucdeg 下划线让您以更小的单位思考,而不是一个包含多个工作的胖函数。我们鼓励您编写小的功能单元,将它们加入到顺序操作中以形成更大的处理单元。
      【解决方案7】:

      这是另一种方式。这个利用了下划线中的 compose 函数。为什么要作曲? compose 得到数学范畴论的支持。这种方式也是免积分的。

      var pluckMyProp = function(array) {
          return _.pluck(array, 'myProperty')
      }
      
      var reject = function(array) {
          return _.reject(array, function(element) {
              return element['ignore'] === true
          })
      }
      
      var finalArray = _.compose(pluckMyProp, reject)
      var data = [{myProperty: 1, ignore: false}, {ignore: true}, {myProperty: 2}]
      
      
      finalArray(data) //=> [1,2]
      

      【讨论】:

      • 要将上面的下划线转换为 lodash,请将 _.pluck 更改为 _map & _.compose 到 _.flowRight。
      猜你喜欢
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      • 1970-01-01
      • 2019-05-24
      • 2013-02-12
      • 1970-01-01
      相关资源
      最近更新 更多