过滤和映射在相同的迭代

我有这种简单的情况,我想筛选和映射到相同的值,如下所示:

const files = results.filter(function(r){ return r.file; }) .map(function(r){ return r.file; }); 

为了节省代码行数,以及提高性能,我正在寻找:

 const files = results.filterAndMap(function(r){ return r.file; }); 

这是否存在,或者我应该自己写点什么? 我在一些地方想要这样的function,以前从来没有打扰过这个function。

       

网上收集的解决方案 "过滤和映射在相同的迭代"

如果你真的需要在1个函数中做,你需要像这样使用reduce

 results.reduce( // add the file name to accumulator if it exists (acc, result) => result.file ? acc.concat([result.file]) : acc, // pass empty array for initial accumulator value [] ) 

如果你需要挤出更多的性能,你可以改变concatpush并返回原始的累加器数组,以避免创build额外的数组。

然而,最快的解决scheme可能是一个很好的旧for循环,避免所有的函数调用和堆栈帧

 files = [] for (var i = 0; i < results.length; i++) { var file = results[i].file if (file) files.push(file) } 

但是我认为filter/map方法更具performance力和可读性

传感器

在其最一般的forms中,你的问题的答案在于换能器 。 但是在我们抽象之前,先来看一些基础知识 – 下面我们实现一个传感器mapReducefilterReducetapReduce ; 你可以添加任何你需要的。

 const mapReduce = map => reduce => (acc, x) => reduce (acc, map (x)) const filterReduce = filter => reduce => (acc, x) => filter (x) ? reduce (acc, x) : acc const tapReduce = tap => reduce => (acc, x) => (tap (x), reduce (acc, x)) const tcomp = (f,g) => k => f (g (k)) const concat = (xs,ys) => xs.concat(ys) const transduce = (...ts) => xs => xs.reduce (ts.reduce (tcomp, k => k) (concat), []) const main = transduce ( tapReduce (x => console.log('with:', x)), filterReduce (x => x.file), tapReduce (x => console.log('has file:', x.file)), mapReduce (x => x.file), tapReduce (x => console.log('final:', x))) const data = [{file: 1}, {file: undefined}, {}, {file: 2}] console.log (main (data)) // with: { file: 1 } // has file: 1 // final: 1 // with: { file: undefined } // with: {} // with: { file: 2 } // has file: 2 // final: 2 // => [ 1, 2 ] 

为了提高性能,你必须测量什么解决scheme会更快。 让我们玩一下https://jsperf.com/filter-than-map-or-reduce/1

任何其他testing用例都是受欢迎的

在这里输入图像描述

如果你想玩基准对NodeJS(记得npm i benchmark

 var suite = new (require('benchmark')).Suite function getSampleInput() { return [{file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}, {file: 'foo'}, {other: 'bar'}, {file: 'baz'}, {file: 'quux'}, {other: 'quuxdoo'}, {file: 'foobar'}] } // author https://stackoverflow.com/users/3716153/gaafar function reduce(results) { return results.reduce( (acc, result) => result.file ? acc.concat([result.file]) : acc , [] ) } // author https://stackoverflow.com/users/1223975/alexander-mills function filterThanMap(results) { return results.filter(function(r){ return r.file; }) .map(function(r){ return r.file; }); } // author https://stackoverflow.com/users/5361130/ponury-kostek function forEach(results) { const files = []; results.forEach(function(r){ if(r.file) files.push(r.file); }); return files } suite .add('filterThanMap', function() {filterThanMap(getSampleInput())}) .add('reduce', function() {reduce(getSampleInput())}) .add('forEach', function() {forEach(getSampleInput())}) .on('complete', function() { console.log('results:') this.forEach(function(result) { console.log(result.name, result.count, result.times.elapsed) }) console.log('the fastest is', this.filter('fastest').map('name')[0]) }) .run() 

为什么不只是forEach

 const files = []; results.forEach(function(r){ if(r.file) { files.push(r.file); } }); 

您可以使用o.file或concat的值和一个空数组作为结果。

 results.reduce((r, o) => r.concat(o.file || []), []); 

你可以使用Array.prototype.reduce()

 const results = [{file:{file:1}}, {notfile:{file:1}}]; const files = results.reduce(function(arr, r){ return r.file ? arr = [...arr, r.file.file] : arr; }, []); console.log(files); // 1 
  const file = (array) => { return array.reduce((acc,curr) => curr.file ? acc.concat(curr) : acc, []) } 

过程:

acc初始化为[](空数组)。 减less文档