【问题标题】:How do you reverse an iterator's flow?如何反转迭代器的流程?
【发布时间】:2017-11-10 10:40:12
【问题描述】:

是否可以访问迭代器的前一个值,例如:

function* gen () {
   yield* [0,1,2,3]
}

var it = gen();

it.next().value // 0
it.next().value // 1
it.last().value // would be awesome if this was 0

这完全是一个好奇心问题。我最近一直在玩生成器,想知道是否有人以这种方式使用生成器/迭代器?

如果是这样,我很乐意看到您的解决方案。 (不需要按照上面的语法)-谢谢

【问题讨论】:

  • last 是指之前的值吗?
  • 我的意思是以前的产量...你认为我应该重新格式化代码以使其更清晰吗?
  • 你不能。迭代器协议不提供这样的 API。
  • @FelixKling 但是你可以为生成器制作一个包装器;看我的回答。
  • @MichałPerłakowski:当然,人们总是可以实现自己的解决方案 :)

标签: javascript ecmascript-6 iterator generator


【解决方案1】:

您可以将生成器包装在一个函数中,以保存以前的产量:

const wrapGenerator = gen => (...args) => {
  const it = gen(...args);
  let previous, current;
  return {
    next: () => {
      const r = it.next();
      previous = current;
      current = r.value;
      return r;
    },
    previous: () => ({ value: previous })
  };
};

const gen = wrapGenerator(function * () {
  yield * [0, 1, 2, 3];
});

const it = gen();

console.log(it.next().value);
console.log(it.next().value);
console.log(it.previous().value);

我将函数名称更改为 previous 以避免混淆(last 可能表示“最后一项”)。

【讨论】:

  • OP 使用last 作为时间参考,但它会与last item 混淆。为什么不调用方法prevprevious
  • @MajidFouladpour prev 可能会导致期望它使生成器朝相反的方向前进,但它不会
【解决方案2】:

JS 迭代器只知道一个方向:向前。这意味着,如果您想将自定义迭代器与 for 循环等一起使用,它将忽略您的自定义属性。但是,您可以创建自己的 custom iterator 仅供您自己使用:

const obj = {
   values: [0,1,2,3],
   [Symbol.iterator]() {
     const values = this.values;
     const min = 0;
     const max = values.length - 1;

     let index = -1;

     return {
       next() {
        index = Math.min(index + 1, max);
        return { value: values[index], done: index >= max };
       },
       prev() {
        index = Math.max(index - 1, min);
        return { value: values[index], done: index <= min };
       }
     }
   }
}

var it = obj[Symbol.iterator]();

console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.prev().value); // would be awesome if this was 0
console.log(it.prev().value); // would be awesome if this was 0
console.log(it.prev().value); // would be awesome if this was 0
console.log(it.next().value); // would be awesome if this was 1

【讨论】:

    【解决方案3】:

    不,这通常是不可能的。 Iterators 只能高级,不能反转或其他。

    当然,您可以编写自己的迭代器包装器来缓存最后一个值并使其以您喜欢的任何方式访问。

    【讨论】:

      猜你喜欢
      • 2021-05-26
      • 1970-01-01
      • 2020-11-06
      • 2012-05-09
      • 2020-05-21
      • 2010-10-27
      • 2011-04-17
      相关资源
      最近更新 更多