array - Python 3 vs Python 2 map comportamiento
python map dictionary (3)
En Python 2, un lenguaje común (antiguo, heredado) es usar el map
para unir iteradores de longitud irregular utilizando el formulario de map(None,iter,iter,...)
así:
>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]
En Python 2, se extiende para que el iterador más largo tenga la longitud de la lista devuelta y si uno es más corto que el otro, se rellena con None
.
En Python 3, esto es diferente. Primero, no puede usar None
como un argumento para la llamada en la posición 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
Bien, puedo arreglar eso así:
>>> def f(*x): return x
...
>>> list(map(f, *(range(5),range(10,12))))
[(0, 10), (1, 11)]
Pero ahora tengo un problema diferente: el map
devuelve la longitud del iterador más corto , ya no se rellena con None
.
Como transfiero el código Python 2 a Python 3, este no es un lenguaje raro y terrible, y no he descubierto una solución fácil de instalar.
Desafortunadamente, las herramientas 2to3 no recogen esto, lo que sugiere inútilmente:
-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18))))
Sugerencias?
Editar
Hay una discusión sobre qué tan común es este idioma. Ver esta publicación tan
Estoy actualizando el código legado escrito cuando aún estaba en la escuela secundaria. Mire los tutoriales de Python de 2003 escritos y discutidos por Raymond Hettinger con este comportamiento específico del mapa que se señala ...
Responderé a mi propia pregunta esta vez.
Con Python 3x, puedes usar itertools.zip_longest así:
>>> 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)]
También puedes rodar tu propio, supongo:
>>> 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)]
puede resolver el problema de esta forma: list(map(lambda x, y: (x, y),[1, 2, 3 ,4, 5], [6, 7, 8, 9, 10]))
itertools.zip_longest
hace lo que quieres, con un nombre más comprensible. :)