1

How do I detect that I iterated over a new item in a list?

I know I can do the varible += 1 after each loop, but I don't want to do that. I'll do it if I have to.

I want something like:

for i in list:
    if i.iterated:
        ...

But of course that won't work.

For example:

list = ['h', 'e', 'l', 'l', 'o']
for i in list:
    pass # I want to add a space (' ') between 'h' and 'e', and join everything after it

In other words, detect when I move on to another iteration

hprogram
  • 61
  • 5
  • If its a small list you could use `pop() `. But When you do use a `for` loop you basically iterate over every element. May be you could expand your question a bit – Beginner Aug 08 '14 at 00:37
  • 3
    What do you mean by "iterated over a new item"? Are you trying to detect items that weren't in the list the last time you looped over it? Or are you trying to detect that you've moved on to the next loop iteration? Because you can tell that you've moved on to the next iteration simply by where in the code you are. – user2357112 Aug 08 '14 at 00:40
  • 2
    I'm not exactly sure what the question here is ... Can you elaborate? doing `for i in lst` will only yield each item once unless your list contains multiple references to the same item. Is that what you're trying to avoid? – mgilson Aug 08 '14 at 00:40
  • @user2357112 detect that I've moved on the the next loop iteration. – hprogram Aug 08 '14 at 00:44
  • The edited version still doesn't help. You've _always_ moved to a new location each time you enter the `for` loop. – abarnert Aug 08 '14 at 00:47
  • Also, what's wrong with slicing, e.g., `lst[0] + ' ' + ''.join(lst[1:])`? Why even use iteration? – abarnert Aug 08 '14 at 00:47
  • Oh yeah! Nice point! I almost forgot! Thanks. I'll try that. – hprogram Aug 08 '14 at 00:50
  • PROBLEM! I want to **insert** ' ' between [0] and [1], not add ' ' to [0] and join the joined[1] w/[0] – hprogram Aug 08 '14 at 00:55
  • @hprogram: Your description is very unclear. You say you want to "join everything after", which suggests you want to concatenate list elements into a single string. In that case, abarnert's code should do exactly what you want. If "insert" is supposed to be inserting a new list item (in which case you probably want the [`insert`](https://docs.python.org/2/library/stdtypes.html#mutable-sequence-types) method), it's not clear what the joining is supposed to be. – user2357112 Aug 08 '14 at 00:59

2 Answers2

4

First, to avoid keeping track of a count yourself, you can use enumerate:

for index, value in enumerate(seq):

Now you'll always know which index goes with the current value. For example:

>>> for index, value in enumerate(['a', 'b', 'c']):
...     print(index, value)
0 a
1 b
2 c

Another alternative is to create an iterator, then loop over that:

it = iter(seq)
for value in it:

Now, the original sequence will still have all of the values, but it will only have the values you haven't yet looked at.

Or, if you want to, you can manually call next on it, so you stop at a certain point, or use a function like itertools.takewhile to do that for you, or…


If you don't want to keep the values at all, you can destructively modify the sequence:

while True:
    try:
        value = seq.pop(0)
    except IndexError:
        break

(Note that this one can be slow with large lists, because popping off the beginning has to shift the whole list up. If you can pop from the end instead of the beginning, or use a deque instead, that problem goes away.)


If you want to, e.g, keep track of how far you got last time so you can pick up from that point next time, either iter or enumerate should be enough to do the trick. But if not, you can always store a list of indexes that you've seen so far, or make the list hold [actual_value, False] pairs and set i[1] = True when you see them, etc. (That would be a big waste of space—and, more importantly, code complexity—unless you have a good reason for it.)

abarnert
  • 354,177
  • 51
  • 601
  • 671
0

Reading between the lines, I think the issue you are having is that you are modifying the list while iterating through it. This is bad form in general as the resulting behavior is not specified.

For should iterate on a copy of the list and then modifications you make on the underlying list do not affect your iterator.

See this previous answer for better a better strategy than modifying a list while iterating over it. I think this article is also a good explanation of the problem.

ADDED

In a simple case like you have, you could also use a while loop with an integer and when you add an extra item to the list, increment your loop control variable a 2nd time too.

Community
  • 1
  • 1
Gary Walker
  • 8,831
  • 3
  • 19
  • 41