5

I have a list of items with heterogeneous data types contained in strings.

lst=['1','err','-1',' ','155']

From that, I would like to obtain a new list with only the positive numbers: new_lst=[1,155]

I have tried to avoid negative numbers as shown below. However, I am not able to avoid the strings and empty strings:

lst1=int(lst)
for i in lst1:
    if i<0:
    print i
    else:
    continue

Traceback (most recent call last):
  File "C:/Users/Dev/Documents/Assignment-2/test-2.py", line 22, in <module>
    c3=int(row[3])
ValueError: invalid literal for int() with base 10: 'err'
>>> 
Serge Stroobandt
  • 28,495
  • 9
  • 107
  • 102
  • Possible duplicate of [Checking whether a variable is an integer or not](http://stackoverflow.com/questions/3501382/checking-whether-a-variable-is-an-integer-or-not) – Ryan Oct 16 '15 at 18:54
  • 1
    This sounds like homework so instead of giving you working code, I will give you an idea of how to solve it. First, iterate your list and for each item in the list, `try` to convert it to an `int`. If the conversion is successful, check to see if the number is greater than 0. If so, then you can add it to your list of positive numbers. – Josh J Oct 16 '15 at 18:58
  • Wrap your "int()" call in a try / except. – RobertB Oct 16 '15 at 19:00

5 Answers5

3
lst=['1','err','-1',' ','155']
newlst = []
for i in lst:
    try:
        if int(i) >= 0:
            newlst.append(int(i))
    except ValueError:
        pass
BigZ
  • 836
  • 8
  • 19
2

lst1=int(lst) is the code that is raising the exception. This is essentially trying to cast a list into an int (which you cannot do).

What you want to do is iterate through lst, and for each element, determine if the element can be cast into an int, then check if the element (as an int) is positive.


You could do something like this:

lst = ['1','err','-1',' ','155']
new_lst = []

for i in lst:
    try:
        int_i = int(i)           # try to cast i to an int
        if int_i > 0:
            new_lst.append(int_i)
    except ValueError:           # ValueError is raised, i cannot be cast into an int
        pass                     # continue to the next element

EDIT: Added ValueError for completeness, see @BigZ's answer.

budi
  • 6,351
  • 10
  • 55
  • 80
2

Here is a one liner that tests if an element is actually a number. If this check isn't done, int(x) will not work and throw and exception.

lst=['1','err','-1',' ','155']
lst1 = filter(None,[(lambda x: x if x.isdigit() and int(x) > 0 else None) (x) for x in lst])
keda
  • 559
  • 2
  • 12
2

If you just have ints and considering you only want to keep positive numbers str.isdigit is sufficient as you don't care if "-1" fails on str.isdigit:

lst[:] = (ele for ele in lst if ele.isdigit() and int(ele) > 0)

If you did possibly have floats then all the answers using int and a try/except would also fail, if you want to cover "1.0" etc.. you would need to cast to float in the try.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

You can utilize pd.to_numeric with argument coerce to essentially remove non-numbers by changing them to Nan, and then extract only positive numbers.

[x for x in  pd.to_numeric(lst, errors='coerce') if x > 0]
Saeed
  • 1,848
  • 1
  • 18
  • 26