3
votes

Un objet itérateur de carte dans Python3.x ne peut-il être utilisé qu'une seule fois et pourquoi? (codes et exemples joints)

Avec ce code:

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

Ici, j'ai une liste de chaînes avec des chaînes comme éléments.

Ensuite, je compte les nombres de ' 0 'et' 1 'respectivement pour chaque chaîne de chaînes et enregistrez les résultats dans count (je l'ai fait en utilisant map en python3, donc count est un objet de carte).

Après cela, je trie compte pour la première fois, et cela fonctionne très bien, mais quand je trie compte pour la deuxième fois, cela renvoie une liste vide ( cntSortBy1 est vide),

Je trouve que c'est parce que count est devenu vide après le premier tri :

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

Pas étonnant que cntSortBy1 soit vide, mais pourquoi à quelle dose cela se produit?

De plus, si j'imprime simplement liste (comptes) , cntSortBy1 deviendra également vide, comme indiqué ci-dessous, p >

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'

  • Dose cela signifie qu'un objet cartographique ne peut être utilisé qu'une seule fois, après quoi il deviendra une liste vide?

  • Y a-t-il d'autres objets dans Py3 avec la même fonctionnalité? (J'ai essayé range () , ce n'est pas le cas.)

Merci beaucoup !!!


1 commentaires

Au lieu d'une carte, vous pouvez essayer count = [[x.count ('0'), x.count ('1')] for x in strs]


3 Réponses :


2
votes

En Python3, map renvoie un itérateur: https://docs.python.org/3/library/functions.html# map

Et les itérateurs ne peuvent (et devraient) être utilisés qu'une seule fois. Voir la documentation officielle sur les itérateurs: https://docs.python.org/3/tutorial/classes.html# itérateurs

Dans votre cas, vous devez convertir map en liste lors de la création, cela résoudra votre problème:

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


1 commentaires

Ce qui, pour être honnête, serait plus pythonique écrit comme count = [[x.count ('0'), x.count ('1')] for x in strs]



0
votes

Une fois qu'un itérateur a été épuisé (c'est-à-dire qu'il a été entièrement itéré), il ne reste plus rien à répéter, donc l'itérer une deuxième fois ne donnera rien. Prenons cet exemple.

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]

Cela affichera:

1
2
3
1
2
3

Chaque fois que vous avez besoin d'itérer plusieurs fois sur un itérateur, transformez-le en liste (ou un autre type de séquence):

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

Ceci génère:

1
2
3

Lors de l'utilisation de sorted () , vous itérez également sur l'objet itérateur map :

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

for i in a:
    print(i)

for i in a:
    print(i)


0 commentaires

0
votes

D'après la documentation: https://docs.python.org/ 3 / library / functions.html # map

carte (fonction, itérable, ...)
Renvoie un itérateur qui applique une fonction à chaque élément d'itérable, donnant les résultats.

/ p>

Par conséquent, lorsque vous avez terminé l'itération sur l'itérateur compte renvoyé par map (lambda x: [x.count ('0'), x.count ('1')] , strs) via trié (count, key = lambda x: x [0]) , il devient vide

Pour éviter cela, vous devez lancer n'importe quel itérateur vous voulez réutiliser dans une liste en utilisant list (map (...)) et ensuite vous pouvez l'utiliser autant que vous le souhaitez, par exemple.

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


0 commentaires