I want to restart iteration after the iterator reaches to done state. Just look at the example:
const newMap = new Map<string, string>([
['key1', 'value1'],
['key2', 'value2']
]);
const iterator = newMap.values() // It can be newMap.entries()
iterator.next().value // prints value1
iterator.next().value //prints value2
iterator.next().value //prints undefined
I just want something like:
iterator.restart();
iterator.next().value // prints value1
CodePudding user response:
Call .values
(or whatever method it was) again.
const newMap = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
let iterator = newMap.values() // It can be newMap.entries()
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) //prints value2
console.log(iterator.next().value) //prints undefined
iterator = newMap.values()
console.log(iterator.next().value) // prints value1
Iterators aren't reusable - you have to create them anew every time you want to start from the beginning.
CodePudding user response:
If you want endlessly repeating values, you can make a generator function that caches the values the first time around and then keeps giving you the cached from the start forever:
function* repeat(iterable) {
const cache = [];
//lazily supply the values from the iterable while caching them
for (const next of iterable) {
cache.push(next);
yield next;
}
//delegate to the cache at this point
while(true)
yield* cache;
}
const newMap = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
const iterator = repeat(newMap.values()) // It can be newMap.entries()
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
Alternatively, if you do not want to cache, you can make the repeat()
implementation simpler by taking a function which gives you an iterable. Any time you call it, you get a new one and delegate to it forever:
function* repeat(iterableSupplier) {
//delegate to the value from the supplier
while(true)
yield* iterableSupplier();
}
const newMap = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
const iterator = repeat(() => newMap.values()) // It can be newMap.entries()
// give a function ^^^^^
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
console.log(iterator.next().value) // prints value1
console.log(iterator.next().value) // prints value2
See more about:
function*
- generator functionsyield*
- delegating to to another iterable- Iterators and generators - about more on the topic in general
CodePudding user response:
You could craft your own iterator that, when asked to, calls newMap.values() again:
const newMap = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
const myIterator = (() => {
let currentIterator = newMap.values();
return {
next() {
return currentIterator.next();
},
restart() {
currentIterator = newMap.values();
}
}
})()
console.log(myIterator.next().value) // prints value1
console.log(myIterator.next().value) //prints value2
console.log(myIterator.next().value) //prints undefined
myIterator.restart();
console.log(myIterator.next().value) // prints value1