Tengo una lista de listas desiguales. Me gustaría generar una nueva lista con comprensión de lista a partir de las sublistas.
s = [['a','b','c','d'],['e','f','g'],['h','i'],['j','k','l','m']]
Estoy probando el siguiente código pero sigue generando un indexError:
new_s = [] for i in range(len(s)): new_s.append((i,[t[i] for t in s if t[i]))
La salida esperada sería:
new_s = [(0,['a','e','h','j']),(1,['b','f','i','k']),(2,['c','g','l']),(3,['d','m'])]
¿Alguna idea de cómo hacer que esto funcione?
Puede usar itertools.zip_longest
para iterar sobre cada sublista por elementos, mientras usa None
como el valor de relleno para las sublistas más cortas.
Luego use el filter
para eliminar los valores None
que se usaron del relleno.
Así que todos juntos en una lista de comprensión:
>>> from itertools import zip_longest >>> [(i, list(filter(None, j))) for i, j in enumerate(zip_longest(*s))] [(0, ['a', 'e', 'h', 'j']), (1, ['b', 'f', 'i', 'k']), (2, ['c', 'g', 'l']), (3, ['d', 'm'])]
uno sin itertools pero modificando la lista original.
def until_depleted(): while any(sl for sl in s): yield 1 list(enumerate(list(s_l.pop(0) for s_l in s if s_l) for _ in until_depleted()))
uno sin modificar el original pero con contador
idx = 0 max_idx = max(len(_) for _ in s) def until_maxidx(): global idx while idx < max_idx: yield 1 idx += 1 list(enumerate(list(s_l[idx] for s_l in s if idx < len(s_l)) for _ in until_maxidx()))
Uno más explícito sin la comprensión interior ni generadores de llamadas:
ret = [] idx = 0 max_idx = max(len(_) for _ in s) while idx < max_idx: ret.append(list(s_l[idx] for s_l in s if idx < len(s_l))) idx += 1 print(list(enumerate(ret)))
Esto es sin itertools, pero también sin comprensión, por lo que no sé si cuenta como una solución.
s = [['a','b','c','d'],['e','f','g'],['h','i'],'j','k','l','m']] new_s = [] for i in range(len(s)): tmp = [] for item in s: tmp.extend(item[i:i+1]) new_s.append((i, tmp))