3 回答
TA贡献1845条经验 获得超8个赞
For 循环很聪明,因为它们可以完成它们的工作,它们只是老了,所以从所有像我这样的时髦函数式程序员那里得到年龄歧视的评论。
let take = (arr, predicate, limit) => {
const results = [];
const arrLength = arr.length
for (let i = 0; i < arrLength && results.length < limit; i++) {
if (predicate(arr[i])) {
results.push(arr[i]);
}
}
return results;
}
无论如何,我很想知道其他人对此问题的解决方案,但这对我来说似乎非常有效......也许是原型垫片解决方案?
TA贡献1797条经验 获得超6个赞
您可以使用生成器或可观察对象以相当优雅的方式完成此操作。
发电机
我实际上为此专门开发了一个小的 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。
TA贡献1803条经验 获得超3个赞
for ... of如果结果数组的长度为 2,您可以使用惰性求值循环并退出。
var array = [1, 2, 3, 4, 5, 6],
result = [];
for (let item of array) {
if (item < 4) if (result.push(item) === 2) break;
}
console.log(result);
添加回答
举报