【问题标题】:Get previous value from generator function从生成器函数中获取先前的值
【发布时间】:2019-09-28 02:18:13
【问题描述】:

我对生成器函数比较陌生,想知道是否有办法从生成器函数中获取先前的值。我知道我可以使用.next() 继续下一个yield,但我想知道是否可以执行.prev() 之类的操作,这实际上会后退一步。

我希望.prev() 能工作,但不幸的是它没有:

const array = ['a', 'b', 'c'];

function* f(array) {
  let i = 0;
  while(true) {
    yield array[i];
    i = (i+1) % array.length;
  }
}

const seq = f(array);
console.log(seq.next().value); // a
console.log(seq.next().value); // b
console.log(seq.next().value); // c

console.log(seq.next().value); // a

// console.log(seq.prev().value); // c <-- expect 'c'

正如我所提到的,我对生成器缺乏经验,如果有更好的数据结构/方法来逐步获取值(上一个和下一个),我愿意听取这些建议

【问题讨论】:

  • Generator 的文档中,您在哪里看到“prev()”(或类似的东西)?您可以轻松编写您的 OWN JS 原型对象,该对象允许您进行任何您想要的操作。但是这个特殊的 JS 原型恰好是“仅向前的”。
  • 可能只有我,但这有什么用例?
  • @paulsm4 嗨,是的,我知道prev() 不是文档的一部分,我只是用来帮助解释我所追求的想法/概念
  • @Shnick 使用合适的数据结构,而不是使用不是为这种情况设计的生成器,您可以简单地使用循环链表并保存最后使用值的引用,然后朝任何方向前进想要,或者正如certainperformace 所回答的那样,使用数组和模数技术,很高兴看到您正在尝试以多种方式解决一个问题,我很欣赏这一点,即使我一直都这样做,但生成器不是这种情况下 IMO 的好选择
  • @CodeManiac 是的,我同意生成器不适合这种情况,因为我知道它们的局限性和优势

标签: javascript function ecmascript-6


【解决方案1】:

您可以让生成器检查yield 的结果,如果是某个表达式(如'prev'),则减少i 而不是增加它:

const array = ['a', 'b', 'c'];

function* f(array) {
  let i = 0;
  while (true) {
    const incOrDec = (yield array[i]) === 'prev' ? -1 : 1;
    i = (array.length + i + incOrDec) % array.length;
  }
}

const seq = f(array);
console.log(seq.next().value); // a
console.log(seq.next().value); // b
console.log(seq.next().value); // c

console.log(seq.next().value); // a

console.log(seq.next('prev').value); // c <-- expect 'c'

如果您不将功能构建到生成器中,则必须将上一次迭代的结果显式保存在变量中,然后检查它。没有像.prev 这样的内置方法。

我对生成器没有经验,如果有更好的数据结构/方法来逐步获取值(上一个和下一个),我愿意听取这些建议

如果您没有必须使用生成器,并且您的目的是能够向前和向后迭代,那么不要这样做。如果您从生成器开始(例如使用您无法控制的外部函数),那么您可以使用类似于上述方法的方法将生成器转换为可以前后导航的生成器。否则,只需使用您将值放入并查找索引的普通数组,例如:

const array = ['a', 'b', 'c'];

function* f(array) {
  let i = 0;
  while (true) {
    const incOrDec = (yield array[i]) === 'prev' ? -1 : 1;
    i = (array.length + i + incOrDec) % array.length;
  }
}

const cache = [];
const getValue = i => cache[i] || (cache[i] = /* put logic for retrieving value here */ array[i % array.length]);

console.log(getValue(0));
console.log(getValue(1));
console.log(getValue(2));
console.log(getValue(3));
console.log(getValue(4));
console.log(getValue(3));

【讨论】:

  • Like Code Maniac 问:这个用例是什么?这个问题的简单答案是“没有像 .prev 这样的内置方法”。期间。
  • 当然,但只是说这不如演示使用不同方法实现所需功能的方法有用。如果您想知道用例,这是 OP 的问题
  • 感谢您的回答,虽然我知道生成器是为了逐步“向前发展”,但这确实回答了我的问题并给了我想要的东西
  • @CertainPerformance 足够公平,但是我们可以添加注释为什么不适合这种情况(因为它不是为这种情况设计的 AFAIK)以及为什么我们应该使用合适的东西(以及实现相同功能的更简单的方法)以便未来的读者会更好地了解?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 2011-01-26
相关资源
最近更新 更多