3

Is it possible to combine the following python list comprehensions into a single line? I know it's not necessary, I'm just curious.

rows = [row.split() for row in data]
flattened = [float(val) for sublist in rows for val in sublist]

Below is a snippet of the data file,

['  -.2098335E-03  -.2108988E-03  -.2119629E-03  -.2130240E-03  -.2140826E-03', '  -.2151421E-03  -.2161973E-03  -.2172531E-03  -.2183025E-03  -.2193489E-03', '  -.2203825E-03  -.2214097E-03  -.2224521E-03  -.2235475E-03  -.2246843E-03'....]

I'm trying to extract each of the strings and make a single list of numbers. The code above currently does that, I was wanting to see if it could get even more condensed.

Thanks!

3
  • Can you give an example of what data is? Commented Jul 14, 2020 at 17:33
  • 2
    does this help? [float(val) for sublist in [row.split() for row in data] for val in sublist] Commented Jul 14, 2020 at 17:33
  • 1
    edit your question include your data and how you wanna get your output, and what you hav done till Commented Jul 14, 2020 at 17:35

5 Answers 5

2

Since sublist is your row.split(), simply replace it.

data = ['0.3 0.6 0.9', '0.1 0.4 0.3']

flattened = [float(val) for row in data for val in row.split()]

print(flattened) #[0.3, 0.6, 0.9, 0.1, 0.4, 0.3]

If we expand it, it becomes more clear.

data = ['0.3 0.6 0.9', '0.1 0.4 0.3']

#the generator is identically replacing this part
flattened = list()
for row in data:
    for val in row.split():
        flattened.append(float(val))

All of the answers that suggest the solution below, are trying to wrap the source loop with the content loop.

#               v--contents--v      wrapping       v--source       
[float(val) for sublist in (row.split() for row in data) for val in sublist] 

It should be the other way around.

[float(val) for row in data for val in row.split()]
Sign up to request clarification or add additional context in comments.

Comments

1

Nested List Comprehensions

Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops.

When we create a new list (of squares) from the elements of the existing list, using list comprehensions, we write:

l1=[1,2,3]
l2=[i**2 for i in l1]
print(l2)

This gives the output:

[1, 4, 9]

We can also nest two or even more for loops in this comprehension.

For example:

l1=[1,2,3]
l2=[4,5,6]
l3=[[i**2,j**2] for i in l1 for j in l2]
print(l3)

The output:

[[1, 16], [1, 25], [1, 36], [4, 16], [4, 25], [4, 36], [9, 16], [9, 25], [9, 36]]

Similarly:

l1=[1,2]
l2=[3,4]
l3=[5,6]
l4=[[i,j,k] for i in l1 for j in l2 for k in l3]
print(l4)

Output:

[[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]

Similarly your code can be re-written using the help of list comprehensions as:

flattened = [float(val) for sublist in (row.split() for row in data) for val in sublist]

Hope this helped you!

Comments

1

You can just use [float(val) for sublist in (row.split() for row in data) for val in sublist] but it is much more readable (and easier to debug in the future) to keep them out on seperate lines

Comments

0

One liner:

data = ["1 2",
        "3 4",
        "5 6",
        "7 8",
        "9 10"
        ]

rows = [float(val) for row in data for sublist in row.split() for val in sublist]
print(rows)

Returns:

[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 1.0, 0.0]

Comments

0

If the intention is only to merge into a one-liner, you can use a generator expression (thanks to @OneCricketeer) that would generate item only when in demand and making it memory efficient than the lists:

flattened = [float(val) for sublist in (row.split() for row in data) for val in sublist]

5 Comments

I would write (row.split() for row in data) to not make a secondary list
@OneCricketeer wouldn't that create a tuple instead?
@DirtyBit No. Commas create tuples, not parentheses. (The exception is the empty tuple, since () is not a valid parenthesized expression.) Parentheses simply prevent the comma from being interpreted as some other part of Python's grammar (for instance, in the argument list to a function.)
@DirtyBit using curved brackets in comprehensions makes it a generator expression (basically a list that isn't generated in memory, but lazy evaluated). See docs.python.org/3/reference/…
@OneCricketeer and hence memory efficient!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.