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

问题描述:

是否可以结合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']); 
}); 

提高效率的任何其他技巧也将受到感谢。

您可以使用each代替:

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

还要注意的是,你并不需要一个正则表达式,只是找出一个字符串用另一个开始。

+2

连锁是每个人更喜欢的 – 2013-10-03 14:19:36

+0

@itcouldevenbeaboat:可以,我不会使用下划线那么多......在这种特殊情况下,每个'似乎都更具可读性。 – georg 2013-10-03 14:36:21

+0

这不好,因为现在你已经引入了不必要的,可变的结果变量。有人可能会说,在这种情况下你可能会使用'for'循环。 '链'是最好的选择。 – spinningarrow 2015-04-14 16:57:15

下划线通过_.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']更清晰。

+0

这当然是一个答案! – nick4fake 2014-10-10 09:35:12

pimvdb的答案是我们在函数式编程中做的事情/ underscore.js 在同一时间执行这两个步骤有点不成熟。 JS从单独做这些事情中获益不多。

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

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

_.mapFilter(阵列,filterFn,mapFn)...

与链接我们牺牲效率性能。两者都很重要,但总是比另一个更重要。我们不能回头来提高生产力,但事实上我们可以提高绩效。

+0

这值得赞赏! “我们不能回头去提高生产力,但我们可以在事后提高性能。”真棒概念! – 2017-02-17 01:17:41

使用_.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; 
}, []);