Как посмотреть следующее значение в итераторе Javascript - PullRequest
1 голос
/ 12 апреля 2020

Допустим, у меня есть итератор:

function* someIterator () {
    yield 1;
    yield 2;
    yield 3;
}

let iter = someIterator();

... который я смотрю на следующий элемент, который будет повторяться:

let next = iter.next(); // {value: 1, done: false}

... и затем я использую итератор в al oop:

for(let i of iterator)
    console.log(i); 
// 2
// 3

l oop не будет включать в себя элемент, который просматривали. sh Чтобы увидеть следующий элемент, не вынимая его из ряда итераций.

Другими словами, я буду sh реализовать:

let next = peek(iter); // {value: 1, done: false}, or alternatively just 1

for(let i of iterator)
    console.log(i); 
// 1
// 2
// 3 

... и я не хочу делать это без изменения кода для итерируемой функции.

То, что я попробовал, есть в моем ответе. Это работает (вот почему я сделал это ответом), но я волнуюсь, что он создает объект, который является более сложным, чем он должен быть. И я беспокоюсь, что это не сработает в тех случаях, когда «готовый» объект отличается от { value = undefined, done = true }. Так что любые улучшенные ответы очень приветствуются.

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Совсем другая идея - использовать упаковщик, который делает итератор более легким.

function peekable(iterator) {
  let state = iterator.next();

  const _i = (function* (initial) {
    while (!state.done) {
      const current = state.value;
      state = iterator.next();
      const arg = yield current;
    }
    return state.value;
  })()

  _i.peek = () => state;
  return _i;
}

function* someIterator () { yield 1; yield 2; yield 3; }
let iter = peekable(someIterator());

let v = iter.peek();
let peeked = iter.peek();
console.log(peeked.value);

for (let i of iter) {
  console.log(i);
}
1 голос
/ 12 апреля 2020

Вместо функции peek я построил функцию peeker, которая вызывает next, удаляя элемент из итератора, но затем добавляет его обратно, создавая итеративную функцию, которая сначала возвращает захваченный элемент, затем возвращает оставшиеся элементы в итерации.

function peeker(iterator) {
    let peeked = iterator.next();
    let rebuiltIterator = function*() {
        if(peeked.done)
            return;
        yield peeked.value;
        yield* iterator;
    }
    return { peeked, rebuiltIterator };
}

function* someIterator () { yield 1; yield 2; yield 3; }
let iter = someIterator();
let peeked = peeker(iter);

console.log(peeked.peeked);
for(let i of peeked.rebuiltIterator())
    console.log(i);
...