Elegant way to split a list of strings into nested lists with values of type float

Question:

Looking for an elegant way to split/format the below list of strings:

ls = ["12,45 58,96",
      "23,67 94,92 93,10",
      "45,76 33,11 46,33"] 

Goal is nested lists of [x, y] coordinates of type float:

goal = [[[12.0,45.0], [58.0,96.0]],
       [[23.0,67.0], [94.0,92.0], [93.0,10.0]]
       [[etc ......

I have solved this with the below code, but it’s rough (and embarrassing!) and I know there has to be a much more elegant way, maybe using list comprehensions or generators?

s = []

for i in ls:
    i.split(' ')
    s.append(i)

res = [i.split(' ') for i in s] # splits at the space

gen = (map(lambda n: n.split(','), x) for x in res) # split list elements at comma
result = (list(x) for x in gen)

final = []

for i in result: # convert each string to a float
    sublist1 = []
    for x in i:
        sub = []
        for z in x:
            z = float(z)
            sub.append(z)
        sublist1.append(sub)
    final.append(sublist1)

print(list(final))
Asked By: eNath

||

Answers:

You can try list comprehension like this –

newlist = [[[float(v) for v in e.split(',')] for e in st.split()] for st in l]

Output:

[[[12.0, 45.0], [58.0, 96.0]], [[23.0, 67.0], [94.0, 92.0], [93.0, 10.0]], [[45.0, 76.0], [33.0, 11.0], [46.0, 33.0]]]
Answered By: kuro

Using map

a = ["12,45 58,96", "23,67 94,92 93,10", "45,76 33,11 46,33"]
list(map(lambda x: list(map(lambda a: list(map(float, a.split(","))), x.split(" "))), a))
Answered By: Deepak Tripathi

Honestly, there are so many ways to write this, and if it will look elegant or not, it will depend on what you understand by elegance.

If elegance is terseness and straightforwardness, you can do list comprehension:

[[[float(v) for v in c.split(',')] for c in l.split()] for l in ls]

If elegance is purity, you can write a fully "point-free" functional expression (even without lambdas), that look completely alien:

from functools import partial
list(map(list, map(partial(map, list), (map(partial(map, partial(map, float)), map(partial(map, partial(str.split, sep=',')), map(str.split, ls)))))))

Now, if elegance is clarity and maintainability, you do the most obvious and self documented code:

def as_coords(ls):
  for string in ls:
    arr = []
    for coord in string.split():
      x, y = coord.split(',')
      arr.append([float(x), float(y)])
    yield arr

list(as_coords(ls))
Answered By: Rodrigo Rodrigues
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.