问题描述
我最近观看了interesting video on the computerphile,并决定使用JavaScript生成器实现sieve-algorithm。一般而言,我对JavaScript很有信心,但以前从未直接使用过生成器。
这是我到目前为止所拥有的:
function* nextNaturalNumber(n) {
yield n;
yield* nextNaturalNumber(n + 1);
}
function* sieve(n) {
let count = 0;
let g = nextNaturalNumber(2);
while (count++ < n) {
const possiblePrime = g.next().value;
yield possiblePrime;
// here's where I'm stuck:
// how can I filter the values from the nextNaturalNumber-generator stream that are not divisible by 2?
}
}
// print the first 10 primes
for (const prime of sieve(10)) {
console.log(prime);
}
如代码注释中所述,我坚持如何从生成器流中过滤不能被2整除的值,从而执行“筛选”操作。是否有一种简单的方法可以在JavaScript中执行此操作(例如在带yield from sieve(i for i in s if i%n !=0)
的Python中)?
解决方法
通过以下操作,您只能从流中获取奇数:
do {
val = g.next().value;
} while (!(val%2));
这里您可以在代码中对其进行测试:
function* nextNaturalNumber(n) {
yield n;
yield* nextNaturalNumber(n + 1);
}
function* sieve(n) {
let count = 0;
let g = nextNaturalNumber(2);
while (count++ < n) {
let val;
do {
val = g.next().value;
} while (!(val%2));
const possiblePrime=val;
yield possiblePrime;
}
}
// print the first 10 primes
for (const prime of sieve(10)) {
console.log(prime);
}
,
不幸的是,JavaScript没有那么多好的迭代器操作。但是,您可以使过滤器函数循环遍历迭代器,并产生匹配的值:
function* nextNaturalNumber(n) {
// switch to iterative to avoid stack overflows
while(true) {
yield n;
n ++;
}
}
function* filterIter(iter,pred) {
for (const item of iter) {
if (pred(item)) {
yield item;
}
}
}
function* sieve(n) {
let count = 0;
let g = nextNaturalNumber(2);
while (count++ < n) {
const possiblePrime = g.next().value;
yield possiblePrime;
g = filterIter(g,v => v % possiblePrime != 0);
}
}
// print the first 10 primes
for (const prime of sieve(10)) {
console.log(prime);
}