Home > Software engineering >  I have a list that contains only strings even with numbers, I want to convert only the number values
I have a list that contains only strings even with numbers, I want to convert only the number values

Time:10-02

Here is what I tried:

g = ["5", "-2", "4", "C", "D", "9", " ", " "]

new = [int(x) if x == str(range(-100, 100)) else x for x in g]

print(new)

CodePudding user response:

You can test for integers by stripping off a potential - and then testing if the rest isnumeric(). For example:

g = ["5", "-2", "4", "C", "D", "9", " ", " "]

new = [int(x) if x.lstrip('-').isnumeric() else x for x in g]

print(new)
# [5, -2, 4, 'C', 'D', 9, ' ', ' ']

Edit:

As others have pointed out, there are other edges cases which are not in your input. A more robust solution would to define a function that explicitly determines how you want to convert the strings...something more like:

g = ["5", "-2", "4", "C", "D", "9", " 5", " ", "-", "--3", "⓪⑧"]

def str2int(s):
    try:
        return int(s)
    except ValueError:
        return s
    
new = [str2int(n) for n in g]
[5, -2, 4, 'C', 'D', 9, 5, ' ', '-', '--3', '⓪⑧']

CodePudding user response:

I believe your strategy is to generate a set of strings that correspond to the possible numbers and check if each string is in that set.

Here's how you could do it:

numbers = set(str(x) for x in range(-100,100))
new     = [ int(x) if x in numbers else x for x in g ]

This limits you to a specific range of numbers which you need to know in advance (it also doesn't cover cases such as " 3" or "005").

A common way to do this is to "ask for forgiveness rather than permission", which means try to convert every item to a number and use the original string if it fails:

new = list()
for x in g:
    try:    
        new.append(int(x.strip()))  # try to add x as an integer
    except ValueError: 
        new.append(x)       # use original string if it fails

If you must do it in a list comprehension, you can use the .isdigit() method of strings but you have to take into account the or - sign that may be at the first position:

new = [int(x) if x[x[:1] in " -":].isdecimal() else x for x in g]

Note, i'm using . isdecimal() instead of .isnumeric() or .isdigit() to avoid getting errors converting special characters such as '一二三四五' or '2²' for which isnumeric()/isdigit() is True but cannot be processed by int(). There is also the case of leading/trailing spaces which this doesn't cover.

  • Related