2

I have a list which consists irregular words and float numbers, I'd like to delete all these float numbers from the list, but first I need to find a way to detect them. I know str.isdigit() can discriminate numbers, but it can't work for float numbers. How to do it?

My code is like this:

my_list = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
for i in my_list:
    if i.isdigit() == True:
        my_list.pop(i)
# Can't work, i.isdigit returns False
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Mario
  • 921
  • 2
  • 10
  • 22

5 Answers5

10

Use exception handling and a list comprehension. Don't modify the list while iterating over it.

>>> def is_float(x):
...     try:
...         float(x)
...         return True
...     except ValueError:
...         return False

>>> lis = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
>>> [x for x in lis if not is_float(x)]
['fun', 'cool', 'go', 'foo']

To modify the same list object use slice assignment:

>>> lis[:] = [x for x in lis if not is_float(x)]
>>> lis
['fun', 'cool', 'go', 'foo']
Community
  • 1
  • 1
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

Easy way:

new_list = []
for item in my_list:
    try:
        float(item)
    except ValueError:
        new_list.append(item)

Using regular expressions:

import re
expr = re.compile(r'\d+(?:\.\d*)')

new_list = [item for item in my_list if not expr.match(item)]

A point about using list.pop():

When you use list.pop() to alter an existing list, you are shortening the length of the list, which means altering the indices of the list. This will lead to unexpected results if you are simultaneously iterating over the list. Also, pop() takes the index as an argument, not the element. You are iterating over the element in my_list. It is better to create a new list as I have done above.

Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
1

A dead simple list comprehension, adding only slightly to isdigit:

my_list = [s for s in my_list if not all(c.isdigit() or c == "." for c in s)]

This will remove string representations of both int and float values (i.e. any string s where all characters c are numbers or a full stop).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
1

As I understand OP the function should only remove floats. If integers should stay - consider this solution:

def is_float(x):
    try:
        return int(float(x)) < float(x)
    except ValueError:
        return False

my_list = ['fun', '3.25', 'cool', '82.356', 'go', 'foo', '255.224']
list_int = ['fun', '3.25', 'cool', '82.356', 'go', 'foo', '255.224', '42']

print [item for item in my_list if not is_float(item)]
print [item for item in list_int if not is_float(item)]

Output

['fun', 'cool', 'go', 'foo']
['fun', 'cool', 'go', 'foo', '42']
Jon
  • 11,356
  • 5
  • 40
  • 74
0

Regular expressions would do the trick - this code searches each string for the format of a float (including floats starting with or ending with a decimal point), and if the string is not a float, adds it to the new list.

import re    
my_list = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
new_list = []
for pos, st in enumerate(my_list):
    if not re.search('[0-9]*?[.][0-9]*', st):
        new_list.append(st)
print new_list

Creating a new list avoids working on the same list you are iterating on.

Ewans answer is cleaner and quicker, I think.

rabs
  • 333
  • 2
  • 6