Python 3 vs Python 2 comportement de la carte

en Python 2, un idiome commun (ancien, ancien) est d'utiliser map pour joindre les itérateurs de longueur inégale en utilisant la forme map(None,iter,iter,...) comme suit:

>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]

en Python 2, Il est étendu de sorte que l'itérateur le plus long est la longueur de la liste retournée et si l'un est plus court que l'autre il est rembourré avec None .

en Python 3, c'est différent. Premièrement, vous ne pouvez pas utiliser None argument pour le callable en position 1:

>>> list(map(None, range(5),range(10,12)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

OK -- je peux arranger ça comme ça:

>>> def f(*x): return x    
... 
>>> list(map(f, *(range(5),range(10,12))))
[(0, 10), (1, 11)]

mais maintenant, j'ai un autre problème: map renvoie la la plus courte longueur de l'itérateur -- pas plus rembourré avec None .

comme je porte le code Python 2 à Python 3, ce n'est pas un langage rare terrible et je n'ai pas trouvé une solution facile en place.

malheureusement, le 2to3 outils ne ramasser ce vers le haut -- suggérant sans hésitation:

-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18)))) 

Suggestions?


modifier

on discute de la fréquence de cet idiome. Voir ce DONC, après les .

je mets à jour le code écrit quand j'étais encore en haut école. regardez les tutoriels Python 2003 étant écrit et discuté par Raymond Hettinger avec ce comportement spécifique de map étant mis en évidence...

16
demandé sur Community 2012-08-18 07:13:10
la source

3 ответов

itertools.zip_longest fait ce que vous voulez, avec un nom plus compréhensible. :)

18
répondu Dougal 2012-08-18 07:17:58
la source

je vais répondre à ma propre question cette fois.

avec Python 3x, vous pouvez utiliser itertools.zip_longest comme suit:

>>> list(map(lambda *a: a,*zip(*itertools.zip_longest(range(5),range(10,17)))))
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (None, 15), (None, 16)]

vous pouvez aussi rouler votre je suppose:

>>> def oldMapNone(*ells):
...     '''replace for map(None, ....), invalid in 3.0 :-( '''
...     lgst = max([len(e) for e in ells])
...     return list(zip(* [list(e) + [None] * (lgst - len(e)) for e in ells]))
... 
>>> oldMapNone(range(5),range(10,12),range(30,38))
[(0, 10, 30), (1, 11, 31), (2, None, 32), (3, None, 33), (4, None, 34), (None, None, 35), (None, None, 36), (None, None, 37)]
2
répondu the wolf 2012-08-29 04:15:14
la source

vous pouvez résoudre le problème comme ceci: list(map(lambda x, y: (x, y),[1, 2, 3 ,4, 5], [6, 7, 8, 9, 10]))

-1
répondu user9018699 2017-11-28 10:33:27
la source

Autres questions sur