简体   繁体   中英

Remove empty string from list

I just started Python classes and I'm really in need of some help. Please keep in mind that I'm new if you're answering this.

I have to make a program that takes the average of all the elements in a certain list "l". That is a pretty easy function by itself; the problem is that the teacher wants us to remove any empty string present in the list before doing the average.

So when I receive the list [1,2,3,'',4] I want the function to ignore the '' for the average, and just take the average of the other 4/len(l). Can anyone help me with this?

Maybe a cycle that keeps comparing a certain position from the list with the '' and removes those from the list? I've tried that but it's not working.

You can use a list comprehension to remove all elements that are '' :

mylist = [1, 2, 3, '', 4]
mylist = [i for i in mylist if i != '']

Then you can calculate the average by taking the sum and dividing it by the number of elements in the list:

avg = sum(mylist)/len(mylist)

Floating Point Average (Assuming python 2)

Depending on your application you may want your average to be a float and not an int. If that is the case, cast one of these values to a float first:

avg = float(sum(mylist))/len(mylist)

Alternatively you can use python 3's division:

from __future__ import division
avg = sum(mylist)/len(mylist)

You can use filter() :

filter() returns a list in Python 2 if we pass it a list and an iterator in Python 3. As suggested by @PhilH you can use itertools.ifilter() in Python 2 to get an iterator.

To get a list as output in Python 3 use list(filter(lambda x:x != '', lis))

In [29]: lis = [1, 2, 3, '', 4, 0]

In [30]: filter(lambda x:x != '', lis)
Out[30]: [1, 2, 3, 4, 0]

Note to filter any falsy value you can simply use filter(None, ...) :

>>> lis = [1, 2, 3, '', 4, 0]
>>> filter(None, lis)
[1, 2, 3, 4]

The other answers show you how to create a new list with the desired element removed (which is the usual way to do this in python). However, there are occasions where you want to operate on a list in place -- Here's a way to do it operating on the list in place:

while True:
    try:
        mylist.remove('')
    except ValueError:
        break

Although I suppose it could be argued that you could do this with slice assignment and a list comprehension:

mylist[:] = [i for i in mylist if i != '']

And, as some have raised issues about memory usage and the wonders of generators:

mylist[:] = (i for i in mylist if i != '')

works too.

itertools.ifilterfalse(lambda x: x=='', myList)

This uses iterators, so it doesn't create copies of the list and should be more efficient both in time and memory, making it robust for long lists.

JonClements points out that this means keeping track of the length separately, so to show that process:

def ave(anyOldIterator):
    elementCount = 0
    runningTotal = 0
    for element in anyOldIterator:
        runningTotal += element
        elementCount += 1
    return runningTotal/elementCount

Or even better

def ave(anyOldIterator):
    idx = None
    runningTotal = 0
    for idx,element in enumerate(anyOldIterator):
        runningTotal += element
    return runningTotal/(idx+1)

Reduce:

def ave(anyOldIterator):
    pieces = reduce(lambda x,y: (y[0],x[1]+y[1]), enumerate(anyOldIterator))
    return pieces[1]/(pieces[0]+1)

Timeit on the average of range(0,1000) run 10000 times gives the list comprehension a time of 0.9s and the reduce version 0.16s. So it's already 5x faster before we add in filtering.

You can use:

alist = ['',1,2]
new_alist = filter(None, alist)
new_alist_2 = filter(bool, alist)

Result:

new_alist = [1,2]
new_alist_2 = [1,2]
mylist = [1, 2, 3, '', 4]
newlist = []
for i in mylist:
    try:
        newlist.append(int(i))
    except ValueError:
        pass
avg = sum(newlist)/len(newlist)

'' is equivalent to False. If we filter the 0 case out (because 0 is equivalent to False), we can use list comprehension :

[x for x in a if x or x == 0]

Or if we strictly want to filter out empty strings :

[x for x in a if x != '']

This may not be the fastest way.

Edit , added some bench results comparing with the other solutions (not for the sake of comparing myself to others, but I was curious too of what method was the fastest)

ragsagar>
6.81217217445
pistache>
1.0873541832
cerealy>
1.07090902328
Matt>
1.40736508369
Ashwini Chaudhary>
2.04662489891
Phil H (just the generator) >
0.935978889465
Phil H with list() >
3.58926296234

I made the script quickly, using timeit(), I used [0,1,2,0,3,4,'',5,8,0,'',4] as the list. I ran multiple tests, results did not vary.

NOTE: I'm not trying to put my solution on top using speed as a criteria. I know OP didn't specifically ask for speed, but I was curious and maybe some other are.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM