5

我刚刚开始 Python 课程,我真的需要一些帮助。请记住,如果您要回答这个问题,我是新手。

我必须制作一个程序,取某个列表“l”中所有元素的平均值。这本身就是一个非常简单的功能;问题是老师希望我们在进行平均之前删除列表中存在的任何空字符串。

因此,当我收到列表时,[1,2,3,'',4]我希望函数忽略''平均值,而只取其他 4/len(l) 的平均值。谁能帮我这个?

也许是一个循环将列表中的某个位置与列表中的某个位置进行比较并从列表''中删除这些位置?我已经尝试过了,但它不起作用。

4

7 回答 7

13

您可以使用列表推导来删除以下所有元素''

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

然后,您可以通过将总和除以列表中的元素数来计算平均值:

avg = sum(mylist)/len(mylist)

浮点平均值(假设 python 2)

根据您的应用程序,您可能希望平均值为浮点数而不是整数。如果是这种情况,请先将这些值之一转换为浮点数:

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

或者,您可以使用 python 3 的除法:

from __future__ import division
avg = sum(mylist)/len(mylist)
于 2012-10-30T12:33:53.887 回答
7

您可以使用filter()

filter()list如果我们在 Python 3 中传递一个列表和 an 在 Python 2 中返回 a iterator。正如@PhilH 所建议的,您可以 itertools.ifilter()在 Python 2 中使用来获取迭代器。

要在 Python 3 中获取列表作为输出,请使用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]

请注意过滤您可以简单使用的任何虚假值filter(None, ...)

>>> lis = [1, 2, 3, '', 4, 0]
>>> filter(None, lis)
[1, 2, 3, 4]
于 2012-10-30T12:49:12.913 回答
2

其他答案向您展示了如何创建一个删除所需元素的新列表(这是在 python 中执行此操作的常用方法)。但是,在某些情况下,您希望在适当的列表上进行操作——这是一种在适当的列表上进行操作的方法:

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

虽然我认为可以说你可以通过切片分配和列表理解来做到这一点:

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

而且,正如一些人提出了关于内存使用和生成器奇迹的问题:

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

也可以。

于 2012-10-30T12:44:19.273 回答
2
itertools.ifilterfalse(lambda x: x=='', myList)

这使用了迭代器,因此它不会创建列表的副本,并且在时间和内存方面都应该更高效,从而使其对长列表具有鲁棒性。

JonClements 指出,这意味着单独跟踪长度,以便展示该过程:

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

甚至更好

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

减少:

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

平均 range(0,1000) 运行 10000 次的 Timeit 使列表理解的时间为 0.9 秒,减少版本为 0.16 秒。因此,在我们添加过滤之前,它已经快了 5 倍。

于 2012-10-30T12:55:19.377 回答
1

您可以使用:

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

结果:

new_alist = [1,2]
new_alist_2 = [1,2]
于 2015-01-06T03:15:12.780 回答
-1

'' 相当于 False。如果我们过滤掉 0 的情况(因为 0 相当于 False),我们可以使用列表推导:

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

或者,如果我们严格想要过滤掉空字符串

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

这可能不是最快的方法。

编辑,添加了一些与其他解决方案相比的基准结果(不是为了将自己与其他人进行比较,但我也很好奇哪种方法最快)

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

我快速制作了脚本,使用 timeit(),我用作[0,1,2,0,3,4,'',5,8,0,'',4]列表。我进行了多次测试,结果没有变化。

注意:我并不是想以速度为标准将我的解决方案放在首位。我知道 OP 并没有特别要求速度,但我很好奇,也许其他人也很好奇。

于 2012-10-30T12:34:53.403 回答
-1
mylist = [1, 2, 3, '', 4]
newlist = []
for i in mylist:
    try:
        newlist.append(int(i))
    except ValueError:
        pass
avg = sum(newlist)/len(newlist)
于 2012-10-30T12:30:25.663 回答