条件过滤,断路取n

按条件过滤并在具有断路的阵列中取前 n 个结果的最佳方法是什么?


在预定义的项目列表上考虑搜索过滤器:


[1, 2, 3, 4, 5, 6].filter(x => {

  console.log(x);

  return x < 4;

}).take(2) === [1, 2];

// 1

// 2

// true

该take函数不存在,因为过滤器函数只返回一个数组,我想要流的断路功能。是否有使用功能方法的组合会产生这种情况?


IE


// would not process 3, 4, 5, or 6 as the circuit would break at 2.

take([1, 2, 3, 4, 5, 6], x => x < 4, 2) === [1, 2]

如果没有更多元素,该功能也应该停止。IE


take([1, 2, 3], x => x < 4, 4) === [1, 2, 3]


蛊毒传说
浏览 155回答 3
3回答

精慕HU

For 循环很聪明,因为它们可以完成它们的工作,它们只是老了,所以从所有像我这样的时髦函数式程序员那里得到年龄歧视的评论。let take = (arr, predicate, limit) => {&nbsp;&nbsp; const results = [];&nbsp; const arrLength = arr.length&nbsp;&nbsp; for (let i = 0; i < arrLength && results.length < limit; i++) {&nbsp;&nbsp; &nbsp; if (predicate(arr[i])) {&nbsp;&nbsp; &nbsp; &nbsp; results.push(arr[i]);&nbsp;&nbsp; &nbsp; }&nbsp;&nbsp; }&nbsp;&nbsp; return results;&nbsp;}无论如何,我很想知道其他人对此问题的解决方案,但这对我来说似乎非常有效......也许是原型垫片解决方案?

互换的青春

您可以使用生成器或可观察对象以相当优雅的方式完成此操作。发电机我实际上为此专门开发了一个小的 npm 包。使用这个包和 Ramda,你可以得到你想要的结果,如下所示:在 RunKit 中尝试const { genTake, genFilter, genFrom, genToArray } = require("func-generators");const { compose } = require('ramda');const probe = x => (console.log(x),x);const firstTwoUnderFour = compose(&nbsp; &nbsp; genToArray,&nbsp; &nbsp; genTake(2),&nbsp; &nbsp; genFilter(x => probe(x) < 4),&nbsp; //&nbsp; genFilter(x => x < 4),&nbsp; &nbsp; genFrom,&nbsp; &nbsp;&nbsp;);console.log(firstTwoUnderFour([5,6,7,1,6,8,2,9,10,5]));&nbsp; // [1, 2]我在过滤谓词中添加了一个探针,以显示它正在处理哪些元素。您可以从控制台输出中看到它在到达 时立即停止2。基本上,它在这里做的是:从原始数组 (&nbsp;genFrom)生成生成器函数将该生成器函数转换为仅生成与谓词 (&nbsp;genFilter(x => x < 4))匹配的值的生成器函数将该生成器函数转换为仅从步骤 2 (&nbsp;genTake(2)) 中的一个生成前两个值的生成器函数将第 3 步中的生成器函数收敛到一个值数组 (&nbsp;genToArray)take从你发布的答案中更概括的可以写成这样:const take = (arr, predicate, limit) => compose(&nbsp; &nbsp; genToArray,&nbsp; &nbsp; genTake(limit),&nbsp; &nbsp; genFilter(predicate),&nbsp; &nbsp; genFrom,)(arr);这甚至适用于无限的值序列:在 RunKit 中尝试const { genTake, genFilter, genInfinite, genToArray } = require("func-generators");const { compose } = require('ramda');const firstFiveMultiplesOf125 = compose(&nbsp; &nbsp; genToArray,&nbsp; &nbsp; genTake(5),&nbsp; &nbsp; genFilter(x => x % 125 === 0),);console.log(firstFiveMultiplesOf125(genInfinite()));最后要注意的一件事:我在这里使用 Ramda 的 compose 来提高可读性,但您也可以嵌套这些函数调用,或者一个一个地调用它们:const result = genToArray(gnTake(5, filter(x => x < 4, genFrom([1,2,3,4,5,6]))));// or...const gen = genFrom([1, 2, 3, 4, 5, 6]);const first2 = genTake(2, genFilter(x => x < 4, gen));const result = genToArray(first2);可观察对象一种稍微重量级的方法是使用 Observables,例如RxJS库:在 RunKit 中尝试const { from } = require("rxjs")const { take, filter, toArray } = require('rxjs/operators');const probe = x => (console.log(x),x);from([5,6,7,1,6,8,2,9,10,5]).pipe(&nbsp; &nbsp; filter(x => probe(x) < 4),&nbsp; &nbsp; take(2),&nbsp; &nbsp; toArray(),).subscribe(xs => console.log(xs));&nbsp; &nbsp; // [1, 2]您也可以在此处看到它在到达 时立即停止检查数组中的元素2。

繁星点点滴滴

for ... of如果结果数组的长度为 2,您可以使用惰性求值循环并退出。var array = [1, 2, 3, 4, 5, 6],&nbsp; &nbsp; result = [];for (let item of array) {&nbsp; &nbsp; if (item < 4) if (result.push(item) === 2) break;}console.log(result);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript