按条件进行过滤并先获取n个结果导致电路断路的最佳方法是什么?
在预定义的项目列表中考虑搜索过滤器:
[1, 2, 3, 4, 5, 6].filter(x => {
console.log(x);
return x < 4;
}).take(2) === [1, 2];
// 1
// 2
// true
take
函数不存在,因为过滤器函数仅返回一个数组,我希望该流具有断路功能。是否存在使用功能性方法合成的成分?
即
// 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]
如果没有更多元素,该功能也应该停止。即
take([1, 2, 3], x => x < 4, 4) === [1, 2, 3]
答案 0 :(得分:2)
感谢@GeraldoFurtado的哲学观点。 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;
}
无论如何,我很想知道其他人对这个问题的解决方案,但这对我来说似乎相当有效……也许是原型垫片解决方案?
答案 1 :(得分:2)
您可以使用生成器或可观察对象以相当优雅的方式完成此操作。
我实际上是专门为此目的而开发的a little npm package。
使用该软件包和Ramda,您可以这样获得所需的结果:
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)
)相匹配的值的函数genTake(2)
)中一个值的前两个值的函数genToArray
)您发布的答案中较为概括的take
可以这样写:
const take = (arr, predicate, limit) => compose(
genToArray,
genTake(limit),
genFilter(predicate),
genFrom,
)(arr);
这甚至可以处理无限的值序列:
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库:
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
,它就会停止检查数组中的元素。
答案 2 :(得分:1)
如果结果数组的长度为2,则可以进行for ... of
循环并进行惰性计算,然后退出。
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);
答案 3 :(得分:0)
如果老的循环器不能带来美学上的满足,如果您使用嵌入式断路器,则可以(以某种不自然的方式)使用其中的高阶功能之一。像我一样沉迷于他们:
const arr = [2,6,9,8,4,3,7,5];
const res = [];
//first 3 items less than 8
arr.find(n => n<8 ? (res.push(n), res.length==3) : false, res);
console.log(res);
答案 4 :(得分:0)
使用lodash!
take(filter([1, 2, 3, 4, 5, 6], x => x < 4), 2)
答案 5 :(得分:0)
const take = (array, predicate, length) => {
let result= []
let i = 0
while (i <= array.length && result.length < length) {
if (predicate(array[i])) {
result.push(array[i])
}
i++
}
return result;
}
const test1 = take([1, 2, 3, 4, 5, 6], x => x < 4, 4)
console.log(test1)
const test2 = take([1, 2, 3, 4, 5, 6, 7, 8, 9], x => x % 2 === 0, 5)
console.log(test2)