Python3.x 中的映射迭代器对象是否只能使用一次,为什么? (附上代码和例子)

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

使用此代码:

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'

这里我有一个列表 strs 以字符串作为元素。

然后我分别计算 strs 中每个字符串的 '0' 和 '1' 的数量,并将结果保存在 counts 中(我在 python3 中使用 map 做到了这一点,所以 count 是一个地图对象)。

之后我第一次对 counts 进行排序,它工作正常, 但是当我第二次对 counts 进行排序时,它 returns 是一个空列表(cntSortBy1 是空的),

我发现这是因为counts在第一次排序后变空了:

>>> 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)
[]

难怪cntSortBy1是空的,但为什么会这样呢?

另外,如果我只是打印list(counts)cntSortBy1也会变成空的,如下图,

>>> 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
[]

非常感谢!!!

在Python3mapreturns一个迭代器中: https://docs.python.org/3/library/functions.html#map

并且迭代器可以(并且应该)只使用一次。请参阅有关迭代器的官方文档: https://docs.python.org/3/tutorial/classes.html#iterators

在您的情况下,您需要在创建时将 map 转换为 list,这将解决您的问题:

counts = list(map(lambda x: [x.count('0'), x.count('1')], strs))

一旦迭代器用完(意味着完全迭代),就没有任何东西可以迭代了,所以第二次迭代不会产生任何结果。举个例子。

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

for i in a:
    print(i)

for i in a:
    print(i)

这将输出:

1
2
3

每当你需要多次迭代一个迭代器时,把它变成一个列表(或其他类型的序列):

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

这输出:

1
2
3
1
2
3

当使用 sorted() 时,您也在迭代 map 迭代器对象:

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]

根据文档:https://docs.python.org/3/library/functions.html#map

map(function, iterable, ...)
Return an iterator that applies function to every item of iterable, yielding the results.

map 的作用是 returns 一个迭代器,您可以对其进行迭代,但是一旦完成对它的迭代,它就会变空,或者当您继续对其进行迭代时,迭代器的大小会不断减小

因此,当您通过 sorted(counts, key=lambda x: x[0])map(lambda x: [x.count('0'), x.count('1')], strs) 返回的迭代器 counts 进行迭代时,它变为空

为避免这种情况,您需要使用 list(map(...)) 将任何要重复使用的迭代器转换为列表,然后您可以随意使用它,例如。

In [1]:  strs = ["111", "1000", "1000", "1000"]                                                                                                                                                   

In [2]: counts = list(map(lambda x: [x.count('0'), x.count('1')], strs))                                                                                                                          

In [3]: counts)                                                                                                                                                                             
Out[3]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [4]: cntSortBy0 = sorted(counts, key=lambda x: x[0])                                                                                                                                           

In [5]: cntSortBy0                                                                                                                                                                                
Out[5]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [6]: counts                                                                                                                                                                                    
Out[6]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [7]: cntSortBy1 = sorted(counts, key=lambda x: x[1])                                                                                                                                           

In [9]: cntSortBy1                                                                                                                                                                                
Out[9]: [[3, 1], [3, 1], [3, 1], [0, 3]]

In [10]: counts                                                                                                                                                                                   
Out[10]: [[0, 3], [3, 1], [3, 1], [3, 1]]

如您所见,我们使用了两次counts,但它从来没有为空,因为我们现在将其转换为一个列表,即使您迭代了无数次,它仍然完好无损。