我写了这段代码来过滤一系列单词.我为我要过滤的每种类型的单词写了一个过滤函数,并将它们顺序应用到数组中:
const wordArray = rawArray.filter(removeNonDomainWords)
.filter(removeWordsWithDigits)
.filter(removeWordsWithInsideNonWordChars)
.filter(removeEmptyWords)
.filter(removeSearchTerm, term)
.map(word => replaceNonWordCharsFromStartAndEnd(word))
Run Code Online (Sandbox Code Playgroud)
如果我没有弄错的话,这段代码将遍历整个数组六次.
编写一个(在我的场景中更复杂,但仍然很容易)过滤器功能,在逻辑上组合过滤器功能以实现相同的结果,是不是更有效率?
我在功能编程的上下文中学习了过滤器,它应该使我的代码更短更快.这就是为什么我可能没有质疑我在写什么,想着'我在做FP,这一定要好'.
谢谢!
好吧,它会迭代六次,但不一定在整个初始数组上.每次过滤它都会变小.使用一种过滤方法会更有效,但差异可能不如预期的那么大.
如果您仍想使用此解决方案,则可以首先使用最具选择性(即预期过滤掉的过滤器)来提高性能.这样,以下数组将会更小,迭代次数也会减少.
正如@Redu指出的那样(在评论中)您可以使用||运算符链接过滤器.这将确保您只进行一次迭代.
这背后的原因是Array.prototype.filter返回一个新数组.将其与Java StreamAPI 进行比较,后者返回一个流,因此可以通过调用列表"深度优先".这样做的缺点是你最终需要一个终端操作来"收集"你的结果.
在javascript中
rawArray.filter(x)
Run Code Online (Sandbox Code Playgroud)
迭代rawArray并返回一个新的过滤后的数组 - 然后可以对其进行过滤或按原样使用.它将导致x对每个元素的调用rawArray.
在Java中相当于
rawArray.stream().filter(x)
Run Code Online (Sandbox Code Playgroud)
在这一点上实际上什么都不做.不会打电话x.返回值为a Stream,可以在以后使用.它可以进一步过滤,但直到以某种方式收集值 - 通过终端操作 - 才能进行调用.
让我们比较一下javascript
rawArray.filter(x).filter(y).length
Run Code Online (Sandbox Code Playgroud)
到Java
rawArray.stream().filter(x).filter(y).count()
Run Code Online (Sandbox Code Playgroud)
在javascript中,这将首先遍历所有元素rawArray,调用x它们中的每一个,并将结果存储在中间数组中.然后javascript引擎将迭代中间数组的所有元素,调用y每个元素,并将结果存储在第二个中间数组中,然后检查其大小.
在Java中,代码片段将导致VM迭代rawArray首先调用的元素x,如果x是true,则调用y每个元素,如果仍然true递增计数器.没有中间数组,只有一次迭代数据集.
函数式编程很有意思,如果使用得当,它会创建更少的代码,这些代码不那么复杂,理想情况下甚至可能更容易阅读,但它确实将很多责任移交给框架(或引擎或VM或其他),以及重要的是要认识到,看似相似的代码虽然行为相似,但在不同环境中的表现却大相径庭.
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |