互换的青春
您可以使用生成器或可观察对象以相当优雅的方式完成此操作。发电机我实际上为此专门开发了一个小的 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( genToArray, genTake(2), genFilter(x => probe(x) < 4), // genFilter(x => x < 4), genFrom, );console.log(firstTwoUnderFour([5,6,7,1,6,8,2,9,10,5])); // [1, 2]我在过滤谓词中添加了一个探针,以显示它正在处理哪些元素。您可以从控制台输出中看到它在到达 时立即停止2。基本上,它在这里做的是:从原始数组 ( genFrom)生成生成器函数将该生成器函数转换为仅生成与谓词 ( genFilter(x => x < 4))匹配的值的生成器函数将该生成器函数转换为仅从步骤 2 ( genTake(2)) 中的一个生成前两个值的生成器函数将第 3 步中的生成器函数收敛到一个值数组 ( genToArray)take从你发布的答案中更概括的可以写成这样:const take = (arr, predicate, limit) => compose( genToArray, genTake(limit), genFilter(predicate), genFrom,)(arr);这甚至适用于无限的值序列:在 RunKit 中尝试const { genTake, genFilter, genInfinite, genToArray } = require("func-generators");const { compose } = require('ramda');const firstFiveMultiplesOf125 = compose( genToArray, genTake(5), 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( filter(x => probe(x) < 4), take(2), toArray(),).subscribe(xs => console.log(xs)); // [1, 2]您也可以在此处看到它在到达 时立即停止检查数组中的元素2。