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);
添加回答
舉報