从javascript生成器流中过滤值

问题描述

我最近观看了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);
}