I have a list which contains numbers and letters in string format.
mylist=['1','orange','2','3','4','apple']
I need to come up with a new list which only contains numbers:
mynewlist=['1','2','3','4']
If I have a way to check if each item in list can be converted to Integer, I should be able to come up with what I want by doing something like this:
for item in mylist:
if (check item can be converted to integer):
mynewlist.append(item)
How do I check that a string can be converted to an integer? Or is there any better way to do it?
You can use exceptional handling as str.digit
will only work for integers and can fail for something like this too:
>>> str.isdigit(' 1')
False
Using a generator function:
def solve(lis):
for x in lis:
try:
yield float(x)
except ValueError:
pass
>>> mylist = ['1','orange','2','3','4','apple', '1.5', '2.6']
>>> list(solve(mylist))
[1.0, 2.0, 3.0, 4.0, 1.5, 2.6] #returns converted values
or may be you wanted this:
def solve(lis):
for x in lis:
try:
float(x)
return True
except:
return False
...
>>> mylist = ['1','orange','2','3','4','apple', '1.5', '2.6']
>>> [x for x in mylist if solve(x)]
['1', '2', '3', '4', '1.5', '2.6']
or using ast.literal_eval
, this will work for all types of numbers:
>>> from ast import literal_eval
>>> def solve(lis):
for x in lis:
try:
literal_eval(x)
return True
except ValueError:
return False
...
>>> mylist=['1','orange','2','3','4','apple', '1.5', '2.6', '1+0j']
>>> [x for x in mylist if solve(x)]
['1', '2', '3', '4', '1.5', '2.6', '1+0j']
The usual way to check whether something can be converted to an int
is to try
it and see, following the EAFP principle:
try:
int_value = int(string_value)
except ValueError:
# it wasn't an int, do something appropriate
else:
# it was an int, do something appropriate
So, in your case:
for item in mylist:
try:
int_value = int(item)
except ValueError:
pass
else:
mynewlist.append(item) # or append(int_value) if you want numbers
In most cases, a loop around some trivial code that ends with mynewlist.append(item)
can be turned into a list comprehension, generator expression, or call to map
or filter
. But here, you can't, because there's no way to put a try
/except
into an expression.
But if you wrap it up in a function, you can:
def raises(func, *args, **kw):
try:
func(*args, **kw)
except:
return True
else:
return False
mynewlist = [item for item in mylist if not raises(int, item)]
… or, if you prefer:
mynewlist = filter(partial(raises, int), item)
It's cleaner to use it this way:
def raises(exception_types, func, *args, **kw):
try:
func(*args, **kw)
except exception_types:
return True
else:
return False
This way, you can pass it the exception (or tuple of exceptions) you're expecting, and those will return True
, but if any unexpected exceptions are raised, they'll propagate out. So:
mynewlist = [item for item in mylist if not raises(ValueError, int, item)]
… will do what you want, but:
mynewlist = [item for item in mylist if not raises(ValueError, item, int)]
… will raise a TypeError
, as it should.
Fast, simple, but maybe not always right:
>>> [x for x in mylist if x.isdigit()]
['1', '2', '3', '4']
More traditional if you need to get numbers:
new_list = []
for value in mylist:
try:
new_list.append(int(value))
except ValueError:
continue
Note: The result has integers. Convert them back to strings if needed, replacing the lines above with:
try:
new_list.append(str(int(value)))
Source: Stackoverflow.com