admin管理员组

文章数量:1415140

Is it possible to access the previous value of an iterator, for example:

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

This is strictly a curiosity question. I've been playing with generators lately and was wondering if anyone uses generators/iterators in this manner?

If so, I would love to see your solution. (Doesn't need to follow the above syntax) -Thanks

Is it possible to access the previous value of an iterator, for example:

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

This is strictly a curiosity question. I've been playing with generators lately and was wondering if anyone uses generators/iterators in this manner?

If so, I would love to see your solution. (Doesn't need to follow the above syntax) -Thanks

Share Improve this question edited Jun 8, 2017 at 16:04 Andrew Li 58k14 gold badges134 silver badges148 bronze badges asked Jun 8, 2017 at 15:53 Joseph BarnesJoseph Barnes 6405 silver badges10 bronze badges 6
  • 2 By last do you mean the previous value? – Michał Perłakowski Commented Jun 8, 2017 at 15:59
  • I meant the previous yield...Do you think I should reformat the code to make that more clear? – Joseph Barnes Commented Jun 8, 2017 at 16:03
  • You cannot. The iterator protocol doesn't provide such an API. – Felix Kling Commented Jun 8, 2017 at 16:07
  • @FelixKling But you can make a wrapper for generators; see my answer. – Michał Perłakowski Commented Jun 8, 2017 at 16:08
  • @MichałPerłakowski: Sure, one can always implement their own solution :) – Felix Kling Commented Jun 8, 2017 at 16:09
 |  Show 1 more ment

3 Answers 3

Reset to default 5

JS iterators only know one direction: forwards. Meaning, if you would want to use your custom iterator with a for-loop or the like, it would ignore your custom properties. You could however create your own custom iterator for your own use only:

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

You can wrap the generator in a function that saves previous yields:

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

I changed the function name to previous to avoid confusion (last could mean "the last item").

No, this is not generally possible. Iterators can only be advanced, not reversed or anything else.

Of course you can write your own iterator wrapper that caches the last value and makes it accessible in whatever way you like.

本文标签: javascriptHow do you reverse an iterator39s flowStack Overflow