¿Cómo puedo utilizar listas por comprensión para procesar una lista anidada?
Tengo esta lista anidada:
l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
Quiero convertir cada elemento l
en float
. Tengo este código:
newList = []
for x in l:
for y in x:
newList.append(float(y))
¿Cómo puedo resolver el problema con una lista de comprensión anidada?
Ver también: ¿Cómo puedo obtener un resultado plano a partir de una lista por comprensión en lugar de una lista anidada?
Así es como haría esto con una lista de comprensión anidada:
[[float(y) for y in x] for x in l]
Esto le daría una lista de listas, similar a la que empezó con la excepción de que tiene elementos flotantes en lugar de cadenas.
Si desea una lista plana, entonces usaría
[float(y) for x in l for y in x]
Tenga en cuenta el orden del bucle: for x in l
es lo primero en este.
A continuación se explica cómo convertir un bucle for anidado en una lista de comprensión anidada:
Así es como funciona la comprensión de listas anidadas:
l a b c d e f
↓ ↓ ↓ ↓ ↓ ↓ ↓
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
...: for b in a:
...: for c in b:
...: for d in c:
...: for e in d:
...: for f in e:
...: print(float(f))
...:
1.0
In [3]: [float(f)
for a in l
...: for b in a
...: for c in b
...: for d in c
...: for e in d
...: for f in e]
Out[3]: [1.0]
Para tu caso, si quieres una lista plana, será algo como esto.
In [4]: new_list = [float(y) for x in l for y in x]
Otro ejemplo interesante con condiciones if en la mezcla:
In [5]: school_data = [
...: {
...: "students": [
...: {"name": "John", "age": 18, "friends": ["Alice", "Bob"]},
...: {"name": "Alice", "age": 19, "friends": ["John", "Bob"]},
...: ],
...: "teacher": "Mr. Smith",
...: },
...: {
...: "students": [
...: {"name": "Sponge", "age": 20, "friends": ["Bob"]},
...: ],
...: "teacher": "Mr. tom",
...: },
...: ]
In [6]: result = []
In [7]: for class_dict in school_data:
...: for student_dict in class_dict["students"]:
...: if student_dict["name"] == "John" and student_dict["age"] == 18:
...: for friend_name in student_dict["friends"]:
...: if friend_name.startswith("A"):
...: result.append(friend_name)
In [8]: result
Out[8]: ['Alice']
Y aquí está la listcomp
versión.
In [9]: [
...: friend_name
...: for class_dict in school_data
...: if class_dict["teacher"] == "Mr. Smith"
...: for student_dict in class_dict["students"]
...: if student_dict["name"] == "John" and student_dict["age"] == 18
...: for friend_name in student_dict["friends"]
...: if friend_name.startswith("A")
...: ]
Out[9]: ['Alice']
No estoy seguro de cuál es el resultado deseado, pero si utiliza la comprensión de listas, el orden sigue el orden de los bucles anidados, que tiene al revés. Entonces obtuve lo que creo que quieres con:
[float(y) for x in l for y in x]
El principio es: use el mismo orden que usaría al escribirlo como bucles for anidados.
>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]