从 javascript 生成器流中过滤值

问题描述 投票:0回答:4

我最近在计算机爱好者上观看了这个有趣的视频,并决定使用 JavaScript 生成器来实现筛选算法。总的来说,我对 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 中执行此操作(如在 Python 中使用

yield from sieve(i for i in s if i%n !=0)
)?

javascript generator
4个回答
1
投票

不幸的是,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);
}

1
投票

通过以下内容,您只能从流中获得奇数值:

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);
}


0
投票

我担心,也许你正在尝试变得比 JS 编码真正理想的 Pythonic 风格。 JS 鼓励明确您正在使用的变量(而不是像 Python 那样将它们隐藏在调用和过滤堆栈中)。 这个怎么样?

//
// You want to look through all the natural numbers...
//
function* nextNaturalNumber(n) {
    while(true) {
        yield n;
        n++;
    }
}   

function* sieve() {
    //
    // Keep track of the primes you've seen previously
    //
    let previousPrimes = [];
    for (const possiblePrime of nextNaturalNumber(2)) {
        //
        // And for each number, check whether it's divisible by any of those primes
        //
        if (!previousPrimes.find((test) => (possiblePrime % test === 0))) {
            //
            // If it's not, return it as a prime and add it to the 
            // primes you've (now) already seen
            //
            yield possiblePrime;
            previousPrimes.push(possiblePrime);
        }
    }
}

let generator = sieve();
for(let i = 0; i < 10; i++) {
    console.log(generator.next().value);
}


0
投票

从 ECMAScript 2025 开始,我们有了迭代器辅助方法,例如

filter
take
,我们可以这样做:

function* sequence(start) { // Don't use recursion
    while (true) yield start++;
}   

function* sieve() { // Leave out the parameter
    let g = sequence(2); 
    while (true) {
        let prime = g.next().value;
        yield prime;
        g = g.filter(v => v % prime); // an iterator helper method
    }
}

// print the first 10 primes
console.log(...sieve().take(10)); // an iterator helper method

© www.soinside.com 2019 - 2024. All rights reserved.