Search code examples
pythonpython-3.xlistmutable

Is a map iterator object in Python3.x can only be used once and why? (codes and examples attached)


With this code:

strs = ["111", "1000", "1000", "1000"]
# count the numbers of '0' and '1' respectively for each string in strs 
counts = map(lambda x: [x.count('0'), x.count('1')], strs)

cntSortBy0 = sorted(counts, key=lambda x: x[0])  # sort with counts of '0'

cntSortBy1 = sorted(counts, key=lambda x: x[1])  # sort with counts of '1'

Here I have a list strs with strings as elements.

Then I count the numbers of '0' and '1' respectively for each string in strs and save the results in counts (I did this using map in python3, so count is a map object).

After that I sort counts for the first time, and it works fine, but when I sort counts for the second time, it returns an empty list(cntSortBy1 is empty),

I find that this is because counts became empty after the first sort:

>>> strs = ["111", "1000", "1000", "1000"]
>>>  counts = map(lambda x: [x.count('0'), x.count('1')], strs)
>>> cntSortBy0 = sorted(counts, key=lambda x: x[0])  # sort with counts of '0'
>>> list(counts)
[]

No wonder cntSortBy1 is empty, but why dose this happen?

Besides, if I just merely print list(counts), cntSortBy1 will also became empty, as shown below,

>>> strs = ["111", "1000", "1000", "1000"]
>>> counts = map(lambda x: [x.count('0'), x.count('1')], strs)
>>> list(counts)
[[0, 3], [3, 1], [3, 1], [3, 1]]
>>> cntSortBy0 = sorted(counts, key=lambda x: x[0])
>>> cntSortBy0
[]
  • Dose this mean a map object could only be used once, after that it will become an empty list?

  • Is there any other objects in Py3 with the same feature? (I have tried range(), it is not.)

Many Thanks!!!


Solution

  • Once an iterator has been exhausted (meaning, fully iterated over), there is nothing left to be iterated over, so iterating over it a second time won't yield anything. Take this example.

    a = map(int,['1','2','3'])
    
    for i in a:
        print(i)
    
    for i in a:
        print(i)
    

    This will output:

    1
    2
    3
    

    Whenever you need to iterate over an iterator multiple times, turn it into a list (or another type of sequence):

    a = list(map(int,['1','2','3']))
    

    This outputs:

    1
    2
    3
    1
    2
    3
    

    When using sorted(), you're also iterating over the map iterator object:

    a = map(int,['1','2','3'])
    print(sorted(a)) # output: [1, 2, 3]
    print(sorted(a)) # output: []
    
    a = list(map(int,['1','2','3']))
    print(sorted(a)) # output: [1, 2, 3]
    print(sorted(a)) # output: [1, 2, 3]