1

I have nested list of the following form:

my_list = [['Some1', '2', '3.6', '4.5', 'GB2', '6'],
           ['Some2', '3.9', '4', '5', 'HG5', '7.3'],
           ['Some3', '4', '5', '6.1', 'H2D', '8.9']]

Every element of each sublist is a string, but I'd like to turn all purely numeric strings into floats.

So I try the following code:

for row in my_list:
    for k, item in enumerate(row):
        if k in (1, 2, 3, 5):
            item = float(item)

Unfortunately, the nested list remains unchanged. I'm sure I'm making a simple mistake, but I can't see it. Any help (and context) would be appreciated.

4 Answers 4

4

Reassigning the name item will never change the list. Try this instead:

for row in my_list:
    for k in (1, 2, 3, 5):
        row[k] = float(row[k])

Note that Python names are just tags attached to some objects. A line like

item = float(item)

will compute float(item) and then bind the name item to the returned object. This does not do anything to the object item pointed to before. Moreover, in this case it is impossible to mutate the latter object in place -- strings are immutable.

Sign up to request clarification or add additional context in comments.

2 Comments

Which would be considered more Pythonic in this case, a for loop or a list comprehension creating my_list2 like DSM suggests? Is one or the other preferred? My actual lists can reach 100,000 + rows.
@PatrickD: The two answers do different things. The code in my answer mutates the original list in place. The code in DSM's answer creates a new list. Another difference is that the code in my answer hardcodes which columns to convert, and will error out if some value cannot be converted. The code in DSM's answer tries to convert every item, and uses the floating point value instead of the original value if the conversion succeeds. The code in this answer is faster and consumes less memory, provided you want these semantics.
4

You're not affecting the original list; you're simply making a float from some of the elements and giving the name "item" to it in turn. You could use something like

row[k] = float(item)

but I'd probably do something like

def floatify(x):
    try:
        return float(x)
    except ValueError:
        return x

my_list2 = [[floatify(x) for x in row] for row in my_list]

Comments

1
for index1, row in enumerate(my_list):
    for index2, item in enumerate(row):
        try:
            my_list[index1][index2] = (float(item))
        except ValueError:
            pass
print my_list
[['Some1', 2.0, 3.6000000000000001, 4.5, 'GB2', 6.0], 
['Some2', 3.8999999999999999, 4.0, 5.0, 'HG5', 7.2999999999999998], 
['Some3', 4.0, 5.0, 6.0999999999999996, 'H2D', 8.9000000000000004]]

Comments

0

You will need to reassign row elements to new calculated value e.g.

row[k] = float(item)

Comments

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.