Search code examples
pythonenumerate

Reuse of Python object created by enumerate


I have a list of lists that I am searching through to find the indices of duplicates.

listA = [[1,2,3],[3,4,5],[6,7,8],[1,2,3]]
listA_set = [[1,2,3],[3,4,5],[6,7,8]]
enum_listA = enumerate(listA)
listA_indices = []
for i in listA_set:
    listA_indices([j[0] for j in enum_listA if j[1] == i])

The intended outcome is:

listA_indices = [[0,3],[1],[2]]

But instead I am getting:

listA_indices = [[0,3],[],[]]

If I include the enumerate within the in-line for loop (see example below), I receive the correct answer but see a significant reduction in speed. How can I perform this task without losing the enumerate information stored in enum_listA?

for i in listA_set:
    listA_indices([j[0] for j in enumerate(listA) if j[1] == i])

Solution

  • enumerate returns an iterator which can only be iterated once. So once it is exhausted, which is the case after you iterate it in the list comprehension of the first for loop iteration, it will not yield any more items.

    If you want to keep the information, you will have to actually store that data in memory, for example as a list:

    enum_listA = list(enumerate(listA))
    

    Note that this effectively duplicates the information in the list and adds the indexes, so this is wasting a lot of extra memory and might not end up being more efficient than recreating the enumerate object over and over.

    The performance difference you are seeing however comes from the fact that after the first loop iteration, the enumerator is empty, so the list comprehension no longer runs for subsequent iterations.