zip (): como una función incorporada que rellena longitudes desiguales desde la izquierda con el valor Ninguno

¿Existe una función incorporada que funcione como zip (), pero llena los resultados de modo que la longitud de la lista resultante sea la longitud de la entrada más larga y complete la lista desde la izquierda con, por ejemplo, None ?

Ya hay una respuesta usando zip_longest del módulo itertools y la pregunta correspondiente es muy similar a esta. Pero con zip_longest parece que solo puede llenar los datos faltantes de la derecha.

Este podría ser un caso de uso para eso, asumiendo que tenemos nombres almacenados solo así (es solo un ejemplo):

 header = ["title", "firstname", "lastname"] person_1 = ["Dr.", "Joe", "Doe"] person_2 = ["Mary", "Poppins"] person_3 = ["Smith"] 

No hay otra permutación como ( ["Poppins", "Mary"] , ["Poppins", "Dr", "Mary"] ) y así sucesivamente.

¿Cómo puedo obtener resultados como este usando funciones integradas?

 >>> dict(magic_zip(header, person_1)) {'title': 'Dr.', 'lastname': 'Doe', 'firstname': 'Joe'} >>> dict(magic_zip(header, person_2)) {'title': None, 'lastname': 'Poppins', 'firstname': 'Mary'} >>> dict(magic_zip(header, person_3)) {'title': None, 'lastname': 'Smith', 'firstname': None} 

Utilice zip_longest pero las listas inversas.

Ejemplo :

 from itertools import zip_longest header = ["title", "firstname", "lastname"] person_1 = ["Dr.", "Joe", "Doe"] person_2 = ["Mary", "Poppins"] person_3 = ["Smith"] print(dict(zip_longest(reversed(header), reversed(person_2)))) # {'lastname': 'Poppins', 'firstname': 'Mary', 'title': None} 

En sus casos de uso:

 >>> dict(zip_longest(reversed(header), reversed(person_1))) {'title': 'Dr.', 'lastname': 'Doe', 'firstname': 'Joe'} >>> dict(zip_longest(reversed(header), reversed(person_2))) {'lastname': 'Poppins', 'firstname': 'Mary', 'title': None} >>> dict(zip_longest(reversed(header), reversed(person_3))) {'lastname': 'Smith', 'firstname': None, 'title': None} 

Simplemente use zip_longest y lea los argumentos en la dirección inversa:

 In [20]: dict(zip_longest(header[::-1], person_1[::-1])) Out[20]: {'lastname': 'Doe', 'firstname': 'Joe', 'title': 'Dr.'} In [21]: dict(zip_longest(header[::-1], person_2[::-1])) Out[21]: {'lastname': 'Poppins', 'firstname': 'Mary', 'title': None} In [22]: dict(zip_longest(header[::-1], person_3[::-1])) Out[22]: {'lastname': 'Smith', 'firstname': None, 'title': None} 

Dado que las funciones zip * deben poder trabajar en iterables generales, no admiten el llenado “desde la izquierda”, porque primero debe agotar el iterable. Aquí solo podemos voltear las cosas nosotros mismos.

La función generadora genérica de “zip mágico” con un número variable de argumentos (que solo usa funciones de evaluación perezosa y sin bucles de python):

 import itertools def magic_zip(*args): return itertools.zip_longest(*map(reversed,args)) 

pruebas (por supuesto, en el caso de una comstackción de dict, solo se necesitan 2 parámetros):

 for p in (person_1,person_2,person_3): print(dict(magic_zip(header,p))) 

resultado:

 {'lastname': 'Doe', 'title': 'Dr.', 'firstname': 'Joe'} {'lastname': 'Poppins', 'title': None, 'firstname': 'Mary'} {'lastname': 'Smith', 'title': None, 'firstname': None} 
 def magic_zip(*lists): max_len = max(map(len, lists)) return zip(*([None] * (max_len - len(l)) + l for l in lists))