¿Cómo puedo utilizar listas por comprensión para procesar una lista anidada?

Resuelto Boy Pasmo asked hace 11 años • 13 respuestas

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 len 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?

Boy Pasmo avatar Aug 06 '13 13:08 Boy Pasmo
Aceptado

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 les lo primero en este.

Andrew Clark avatar Aug 06 '2013 06:08 Andrew Clark

A continuación se explica cómo convertir un bucle for anidado en una lista de comprensión anidada: ingrese la descripción de la imagen aquí

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 listcompversió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']
Rahul avatar Jul 13 '2017 11:07 Rahul

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.

Harry Binswanger avatar Mar 26 '2017 02:03 Harry Binswanger
>>> 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]
falsetru avatar Aug 06 '2013 06:08 falsetru