The Python Oracle

Comprehension on a nested iterables?

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Darkness Approaches Looping

--

Chapters
00:00 Comprehension On A Nested Iterables?
00:33 Answer 1 Score 56
00:48 Accepted Answer Score 489
01:13 Answer 3 Score 63
01:34 Answer 4 Score 394
02:28 Thank you

--

Full question
https://stackoverflow.com/questions/1807...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #list #nested #listcomprehension

#avk47



ACCEPTED ANSWER

Score 489


Here is how you would do this with a nested list comprehension:

[[float(y) for y in x] for x in l]

This would give you a list of lists, similar to what you started with except with floats instead of strings.

If you want one flat list, then you would use

[float(y) for x in l for y in x]

Note the loop order - for x in l comes first in this one.




ANSWER 2

Score 394


Here is how to convert nested for loop to nested list comprehension:

#   l a b c d e f
#   ↓ ↓ ↓ ↓ ↓ ↓ ↓
l = [ [ [ [ [ [ 1 ] ] ] ] ] ]

new_list = []
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.append(float(f))
                        


new_list = [
    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
]

# new_list => [1.0]

For your case, if you want a flat list, it will be something like this.

new_list = [float(y) for x in l for y in x]

Another interesting example with if conditions in the mix:

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",
    },
]

result = []

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)

And here is the listcomp version

result = [
    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")
]
# result => ['Alice']



ANSWER 3

Score 63


Not sure what your desired output is, but if you're using list comprehension, the order follows the order of nested loops, which you have backwards. So I got the what I think you want with:

[float(y) for x in l for y in x]

The principle is: use the same order you'd use in writing it out as nested for loops.




ANSWER 4

Score 56


>>> 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]