Reputation: 373
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!
Upvotes: 3
Views: 827
Reputation: 5531
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()]
Upvotes: 2
Reputation: 1044
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!
Upvotes: 1
Reputation: 16772
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]
Upvotes: 0
Reputation: 3961
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]
Upvotes: 0
Reputation: 6702
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
Upvotes: 1