Chris
Chris

Reputation: 22953

How to get the type of a varible

I created a function that took a list as a parameter and removed either a space or a number. Code below:

def cleaner(List, filter_out=' '):
    if filter_out == ' ':
        for i in List:
            if i == ' ':
                List.remove(' ')
    if filter_out == 'int':
        for i in List:
            if type(i) == int:
                List.remove(i)

I tested it using a list like so:

myList = ['h' ' ', 'g', 1, 2, 3, 4, 5, 'p']
print(cleaner(myList, filter_out='int'))

I expected to get ['h' ' ', 'g', 'p'] but instead printed out ['h ', 'g', 2, 4, 'p'] Why did it leave the 1 and 2? I thought that it would filter out all numbers in the list.

Upvotes: 1

Views: 85

Answers (2)

zondo
zondo

Reputation: 20336

Removing items from a list while iterating it results in bad consequences:

>>> nums = [1, 2, 3, 4]
>>> for x in nums:
...     print x
...     nums.remove(x)
... 
1
3

You start at index 0. You print nums[0], 1. You then remove it. The next index is 1. Well, [nums[1] is 3 because now the list is [2, 3, 4]. You print that, and remove it. The list is now [2, 4], and you are at the third index. Since nums[2] does not exist, the loop ends, skipping two numbers. What you should do is take advantage of the builtin functions:

myList = ...
myList = filter(lambda x: not isinstance(x, int), myList)

For the example of ' ', it would be:

myList = ...
myList = filter(str.strip, myList)

or

myList = filter(lambda x: x != ' ', myList)

Note: The Python 3 filter() function returns a filter object, not a list. That makes it more efficient if you are just iterating, but if you truly need a list, you can use list(filter(...)).

All of these make a copy of the list instead of doing their work in place. If you want it in place, use myList[:] = ... instead of myList = ... (in the filter() line). Note that a Python 3 filter object does not need to be converted to a list for this to work.

Upvotes: 4

Marko Mackic
Marko Mackic

Reputation: 2333

This would be a proper way to do it for medium sized lists

 def cleaner(lst,filter_item = ' '):
        if filter_item == ' ':
            for i in list(lst):
                if i == ' ':
                    lst.remove(' ')
        elif filter_item == 'int':
            for i in list(lst):
                if type(i) == int:
                    lst.remove(i)

 myList = ['h' ' ', 'g', 1, 2, 3, 4, 5, 'p']
 cleaner(myList, 'int')
 print(myList)

or a nicer way:

 def cleaner(lst,filter_item = ' '):
     retval = None
     if filter_item == ' ':
         retval = [i for i in lst if i != ' ']
     elif filter_item == 'int':
         retval = [i for i in lst if type(i) != int]
     return retval 

myList = ['h' ' ', 'g', 1, 2, 3, 4, 5, 'p']
a=cleaner(myList)
print(a)
#['h ', 'g', 1, 2, 3, 4, 5, 'p']
a=cleaner(myList,'int')
print(a)
#['h ', 'g', 'p']

Upvotes: 1

Related Questions