You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从JavaScript生成器函数的输出结果中去除重复值

生成器去重解决方案

我有三个生成器函数,第三个是委托生成器:

function* genNumbers() {
    yield* [1, 2, 2, 2, 3, 4, 5];
}

function* genLetters() {
    yield* ["A", "B", "B", "B", "C", "D"];
}

function* genAll() {
    yield* genNumbers();
    yield* genLetters();
}

let generator = genAll();

希望调用generator.next()输出所有值时自动去除重复值,预期输出如下:

console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next()); // {value: 2, done: false}
console.log(generator.next()); // {value: 3, done: false}
console.log(generator.next()); // {value: 4, done: false}
console.log(generator.next()); // {value: 5, done: false}
console.log(generator.next()); // {value: "A", done: false}
console.log(generator.next()); // {value: "B", done: false}
console.log(generator.next()); // {value: "C", done: false}
console.log(generator.next()); // {value: "D", done: false}

方案一:修改委托生成器实现去重

直接在genAll内部维护一个集合记录已输出的值,过滤重复项后再yield:

function* genNumbers() {
    yield* [1, 2, 2, 2, 3, 4, 5];
}

function* genLetters() {
    yield* ["A", "B", "B", "B", "C", "D"];
}

function* genAll() {
    const seen = new Set();
    // 遍历数字生成器,去重后输出
    for (const num of genNumbers()) {
        if (!seen.has(num)) {
            seen.add(num);
            yield num;
        }
    }
    // 遍历字母生成器,去重后输出
    for (const letter of genLetters()) {
        if (!seen.has(letter)) {
            seen.add(letter);
            yield letter;
        }
    }
}

let generator = genAll();

// 测试输出
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next()); // {value: 2, done: false}
console.log(generator.next()); // {value: 3, done: false}
console.log(generator.next()); // {value: 4, done: false}
console.log(generator.next()); // {value: 5, done: false}
console.log(generator.next()); // {value: "A", done: false}
console.log(generator.next()); // {value: "B", done: false}
console.log(generator.next()); // {value: "C", done: false}
console.log(generator.next()); // {value: "D", done: false}
console.log(generator.next()); // {value: undefined, done: true}

方案二:通用去重包装生成器

如果不想修改原有生成器,可以写一个通用的去重包装函数,适配任何生成器:

// 通用去重包装生成器
function* dedupeGenerator(generator) {
    const seen = new Set();
    for (const value of generator) {
        if (!seen.has(value)) {
            seen.add(value);
            yield value;
        }
    }
}

function* genNumbers() {
    yield* [1, 2, 2, 2, 3, 4, 5];
}

function* genLetters() {
    yield* ["A", "B", "B", "B", "C", "D"];
}

function* genAll() {
    yield* genNumbers();
    yield* genLetters();
}

// 用包装器处理原生成器
let generator = dedupeGenerator(genAll());

// 测试输出
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next()); // {value: 2, done: false}
console.log(generator.next()); // {value: 3, done: false}
console.log(generator.next()); // {value: 4, done: false}
console.log(generator.next()); // {value: 5, done: false}
console.log(generator.next()); // {value: "A", done: false}
console.log(generator.next()); // {value: "B", done: false}
console.log(generator.next()); // {value: "C", done: false}
console.log(generator.next()); // {value: "D", done: false}
console.log(generator.next()); // {value: undefined, done: true}

思路说明

利用Set数据结构记录已经输出过的值,它的has方法查询效率高(O(1))。遍历生成器的每一个值,仅当值未在Set中时,才将其yield出去并加入Set,确保每次调用next()返回的都是不重复的新值。

内容的提问来源于stack exchange,提问作者Ayman Mirghani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:17:14