如何通过下划线的地图和过滤器实现最高效率?

时间:2012-03-16 14:41:52

标签: javascript underscore.js

是否可以组合Underscore的过滤器和地图?我目前有两个独立的函数调用,但我想知道我是否可以通过将它们组合成一个单独的调用来提高它们的效率。

基本上我有一组国家/地区名称 - 我想使用正则表达式过滤它们,然后将过滤后的结果映射到DataItem对象数组。这是我目前的代码:

var filteredData = _.filter(allCountries, function(n, i){ 
  var re = RegExp("^" + searchString, "i");
  if (re.exec(n['country'].toLowerCase()) !== null) {
    return true;
  }
});
var mappedData = _.map(filteredData, function(n, i){ 
  return new DataItem(i, n['name'], n['budget']);
});

还要感谢任何提高效率的其他提示。

4 个答案:

答案 0 :(得分:33)

Underscore通过_.chain提供链接功能:

_.chain(allCountries)
 .filter(function(n, i) { ... })
 .map(function(n, i) { ... })
 .value(); // stop chaining and get the result

您可以使用re.exec(...) !== null代替re.test(...),并注意您需要转义searchString的特殊正则表达式字符。

但是,在这个简单的情况下,最好使用.indexOf检查字符串是否以子字符串开头:

// substring should be apparent at position 0, discard case for both strings
return n.country.toLowerCase().indexOf(searchString.toLowerCase()) === 0;

对于字符串文字,.foo可能比['foo']更清晰。

答案 1 :(得分:11)

您可以改为使用each

 result = []
_.each(array, function(elem) {
    if(elem.indexOf(search) == 0)
        result.push(...whatever...)

另请注意,您不需要正则表达式来查明字符串是否以另一个字符串开头。

答案 2 :(得分:11)

使用_.reduce,因为它可以保存n次迭代。将RegEx拉出循环,这样就不会在每次迭代时重新创建对象。使用test代替exec(更快,因为它是一个简单的布尔结果)。

var re = RegExp("^" + searchString, "i");
var data = _.reduce(allCountries, function(res, n, i) { 
  if (re.test(n['country'])) {
    res.push(new DataItem(i, n['name'], n['budget']));
  }
  return res;
}, []);

答案 3 :(得分:8)

pimvdb的答案就是我们在函数式编程/ underscore.js中做事的方式 同时执行这两个步骤有点过早优化。 JS分别做这些事情并没有太大的好处。

_.chain(allCountries)
 .filter(function(n, i) { ... })
 .map(function(n, i) { ... })
 .value();

以上内容很容易理解,但一旦我们开始合并责任,事情就会变得毛茸茸。

_。mapFilter(数组,filterFn,mapFn)...

链接我们牺牲了生产力的表现。两者都很重要,但总是一个比另一个更重要。我们不能回头提高生产力,但我们可以在事后提高绩效。