How to Reset an Iterator

java- reset list iterator to first element of the list

Best would be not using LinkedList at all, usually it is slower in all disciplines, and less handy. (When mainly inserting/deleting to the front, especially for big arrays LinkedList is faster)

Use ArrayList, and iterate with

int len = list.size();
for (int i = 0; i < len; i++) {
Element ele = list.get(i);
}

Reset is trivial, just loop again.

If you insist on using an iterator, then you have to use a new iterator:

iter = list.listIterator();

(I saw only once in my life an advantage of LinkedList: i could loop through whith a while loop and remove the first element)

How do you reset an iterator?

The general answer is that you can't reset an iterable in JS. This is, as far as I know, by-design, although I'm not privy to the decision-making process that was used to reach that conclusion.

In your specific case however, you don't want to necessarily reset the iterator, you want to cycle through the array. In that case, you can use the modulo operator as follows:

function nameIterator(names) {
let nextIndex = 0;
return {
next: function() {
nextIndex = (nextIndex + 1) % names.length;
return { value: names[nextIndex], done: false };
}
}
}

Resetting an iterator, which is a map object?

Iterating an iterator/generator consumes the values from it (infinite generators being an exception), meaning that they will no longer be available on future iterations (as you've seen). For a typical iterator/generator in Python, the only true way to "restart" it is to re-initialize it.

>>> sol = map(pow, [1, 2, 3], [4, 5, 6])      
>>> list(sol)
[1, 32, 729]
>>> next(sol)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> sol = map(pow, [1, 2, 3], [4, 5, 6])
>>> next(sol)
1

There are ways that you can work with the iterator to make it reusable though, such as with itertools.tee (as mentioned by one of the answers to the question linked by @JanChristophTerasa), or to convert the iterator into a list, which will persist its data.

itertools.tee

>>> from itertools import tee
>>> sol = map(pow, [1, 2, 3], [4, 5, 6])
>>> a, b = tee(sol, 2)
>>> list(a)
[1, 32, 729]
>>> list(b)
[1, 32, 729]
>>> list(a)
[]

with tee though, both a and b will still be iterators, so you'll have the same problem with them.

Another common way to handle this is with list()

sol = list(map(pow, [1, 2, 3], [4, 5, 6]))
>>> sol
[1, 32, 729]
>>> sol
[1, 32, 729]

Now, sol is a list of values instead of an iterator, which means you can iterate it as many times as you want - the values will remain there. This does mean you can't use next with it (in the sense of next(sol)), but you can get an iterator back from your new list with iter(sol) if you need an iterator specifically.

Edit

I saw itertools.cycle mentioned in the comments, which is also a valid option so I thought I might add some info on it here as well.

itertools.cycle is one of those infinite generators I mentioned at the start. It is still an iterator, but in a way that you'll never run out of values.

>>> from itertools import cycle
>>> sol = map(pow, [1, 2, 3], [4, 5, 6])
>>> infinite = cycle(sol)
>>> for _ in range(5):
... print(next(infinite))
...
1
32
729
1
32
>>>

A few notes on this - after iterating infinite N times, it will be positioned after whatever the last value was pulled from it. Iterating it again later will resume from that position, not from the start.

Also, and this is very important, do not iterate an infinite generator in an unbounded fashion, like list(infinite) or for x in infinite:, or you're gonna have a bad time.

Reset Iterator position to 0 in a nested while-loop

How can I reset itemIterator to position 0 without reinitiating it using items.iterator() because that will bring back items removed from itemIterator for next iteration.

No, it won't. itemIterator.remove() removes the item from the collection you got the iterator from, not just the iterator. If you get a new iterator from that collection, it won't have that item on it anymore; you removed it. From the JavaDoc:

Removes from the underlying collection the last element returned by this iterator (optional operation). This method can be called only once per call to next().

(my emphasis)

You can't reset an iterator; just get a new one, within the while.

Iterator<Event> eventIterator = events.iterator();

while (eventIterator.hasNext()) {
Event event = eventIterator.next();

Iterator<EventItem> itemIterator = items.iterator();
while (itemIterator.hasNext()) {
EventItem item = itemIterator.next();
if (event.getId().equals(item.getEventId())) {
// CLAIMED
itemIterator.remove();
}
}

// If you need to loop a second time for some reason:
itemIterator = items.iterator();
// ...
}

Can iterators be reset in Python?

I see many answers suggesting itertools.tee, but that's ignoring one crucial warning in the docs for it:

This itertool may require significant
auxiliary storage (depending on how
much temporary data needs to be
stored). In general, if one iterator
uses most or all of the data before
another iterator starts, it is faster
to use list() instead of tee().

Basically, tee is designed for those situation where two (or more) clones of one iterator, while "getting out of sync" with each other, don't do so by much -- rather, they say in the same "vicinity" (a few items behind or ahead of each other). Not suitable for the OP's problem of "redo from the start".

L = list(DictReader(...)) on the other hand is perfectly suitable, as long as the list of dicts can fit comfortably in memory. A new "iterator from the start" (very lightweight and low-overhead) can be made at any time with iter(L), and used in part or in whole without affecting new or existing ones; other access patterns are also easily available.

As several answers rightly remarked, in the specific case of csv you can also .seek(0) the underlying file object (a rather special case). I'm not sure that's documented and guaranteed, though it does currently work; it would probably be worth considering only for truly huge csv files, in which the list I recommmend as the general approach would have too large a memory footprint.

In Python, is it a bad practice to "reset" an iterator when __iter__ is called?

iter is expected to have no side effects. By violating this assumption, your code breaks all sorts of things. For example, the standard test for whether a thing is iterable:

try:
iter(thing)
except TypeError:
do_whatever()

will reset your file. Similarly, the itertools consume recipe:

def consume(iterator, n=None):
"Advance the iterator n-steps ahead. If n is None, consume entirely."
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(islice(iterator, n, n), None)

will produce an incorrect file position instead of advancing n records after consume(your_file, n). Skipping the first few records with next before a loop will also fail:

f = MySpecialFile(whatever)
next(f) # Skip a header, or try, anyway.
for record in f:
# We get the header anyway.
uhoh()

Why iterator doesn't have any reset method?

Why?

Because if you force iterator to have a reset method every iterator has to have a reset method. That gives every iterator writer extra work. Plus some iterators are really hard (or really expensive) to reset, and you wouldn't want users to call reset on them. Iterators over files or streams are good examples.

what the best way to move iterator items pointer to the first position?

Create a new iterator. It's rarely more expensive than the reset.

How to reset a loop that iterates over a set?

One way to do so would be by using iterators. You could define an iterator by simply calling iter() on your set, and call its next method on each iteration. When the condition is met, you can simply create again the iterator object from the set and repeat the process:

s = {1,2,3,4,5}
s_ = iter(s)
# Just a counter to avoid endless loop
cont = 0
while cont < 10:
try:
i = next(s_)
except StopIteration:
break
# Some condition
if flag == True:
# Reset the iterator when the condition is met
s_ = iter(s)
continue
cont += 1


Related Topics



Leave a reply



Submit