3

Let's say I have list of lists in matrix variable:

matrix = [['first', '1,1', 'last'], ['strng_1', '12231,71', 'st_2']]

As you can see, all nested lists are having float data written as string. I would like to convert them to float datatype. I need to create a dictionary and make this conversion simultaneously. For that reason, I've tried to make it using dictionary comprehension. So, these operations as one-liner might look like this:

dict_comp = {r[0]: r.insert(1, float(r[1].replace(',', '.'))).pop(2) for r in matrix if r}

But it doesn't work as expected. And now, after my previous question I know why exactly. Finally, I would like to ask about how to generate a dictionary with simultaneous converting certain strings to floats?

UPDATE

Expecting output:

{'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}
Quanti Monati
  • 769
  • 1
  • 11
  • 35

7 Answers7

4

The following will work:

dict_comp = {r[0]: [r[0], float(str(r[1]).replace(',','.')), r[2]] for r in matrix if r}

# {'first': ['first', 1.1, '1,1'], 'strng_1': ['strng_1', 12231.71, 'st_2']}
Carsten
  • 2,765
  • 1
  • 13
  • 28
2

Change your locale to something that would understand comma as a decimal point, for example fr_FR.utf8, use locale.atof to convert the string to float, and then revert back your locale

import locale 
loc = locale.getlocale() 
locale.setlocale(LC_NUMERIC, 'fr_FR.utf8')

d = {a:[a, locale.atof(b), c] for a,b,c in matrix}

locale.setlocale(LC_NUMERIC, loc)

print (d)

Output

{'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}
Sunitha
  • 11,777
  • 2
  • 20
  • 23
1

Per my answer last time:

matrix = [['first', '1,1', 'last'], ['strng_1', '12231,71', 'st_2']]
[[r[0], float(r[1].replace(',', '.')), r[2]] for r in matrix]
# => [['first', 1.1, 'last'], ['strng_1', 12231.71, 'st_2']]

EDIT: If you want to make a dict...

{r[0]: [r[0], float(r[1].replace(',', '.')), r[2]] for r in matrix}
# => {'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}
Amadan
  • 191,408
  • 23
  • 240
  • 301
1

you cant save r.insert(1, float(r[1].replace(',', '.'))).pop(2) as dictionary value. It will be like None.pop(2) which will give you error

As per your edited expected output answer by @Carsten should work.

Rahul
  • 10,830
  • 4
  • 53
  • 88
1

Using dictionary list comprehension

Ex.

matrix = [['first', '1,1', 'last'], ['strng_1', '12231,71', 'st_2']]
new_list = {x[0]: [(float(i.replace(",",".")) if "," in i else i)for i in x ] for x in matrix}
print(new_list)

O/P:

{'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}
bharatk
  • 4,202
  • 5
  • 16
  • 30
1

If the position of the float string is always the same, you can use destructuring assignement in the dict comprehension:

>>> matrix = [['first', '1,1', 'last'], ['strng_1', '12231,71', 'st_2']]
>>> {k: [k, float(f.replace(",", ".")), *l] for k, f, *l in matrix}
{'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}

If the float may be at any position except the first:

>>> def try_to_cast(v):
...    try:
...        return float(v.replace(",", "."))
...    except ValueError:
...        return v
...
>>> {k: [k, *[try_to_cast(v) for v in l]] for k, *l in matrix}
{'first': ['first', 1.1, 'last'], 'strng_1': ['strng_1', 12231.71, 'st_2']}

See @Sunitha's answer for a cleaner method to convert strings to float using locale.

jferard
  • 7,835
  • 2
  • 22
  • 35
0

Think of it as constructing a new list instead of changing and existing one.

Assuming this is what you want to do using a dictionary comprehension:

dict_ = {}
for row in matrix:
    new_row = row[:1] + [float(row[1].replace(',', '.'))] + row[2:]
    dict[row[0]] = new_row

This would then be transformed into:

dict_ = {r[0]: r[:1] + [float(r[1].replace(',', '.'))] + r[2:] for r in matrix if r}

Generally, though, I would advise against such complicated dict comprehensions. It may be shorter but it is less readable.

Kendas
  • 1,963
  • 13
  • 20