列表中的数字,找到周围的平均值

时间:2012-10-11 14:10:07

标签: python list python-3.x

问题:

给定一个数字列表listA,编写一个程序,生成一个新列表listB,其元素数量与listA相同,这样新列表中的每个元素都是原始列表中其邻居及其自身的平均值。

例如,如果listA = [5, 1, 3, 8, 4]listB = [3.0, 3.0, 4.0, 5.0, 6.0],则其中:

(5 + 1)/2 = 3.0 
(5 + 1 + 3)/3 = 3.0 
(1 + 3 + 8)/3 = 4.0 
(3 + 8 + 4)/3 = 5.0 
(8 + 4)/2 = 6.0 

所以我可以获得第一部分,最后部分因为它们只处理2个数字,但是对于中间部分我无法得到它。我的循环是错误的,但我完全不知道。这是我到目前为止所做的。

listA= [5,1,3,8,4]

N=len(listA)
print(listA)

listB=[]
listB.append((listA[0]+listA[1])/2)

y=0
x=1
while x in listA:
    y=((listA[x-1] + list[x] + list[x+1])/3)
    listB.append(y)
y=y+1

listB.append((listA[-1]+listA[-2])/2)

print(listB)

5 个答案:

答案 0 :(得分:3)

您可以使用迭代器执行此操作,而无需通过索引循环:

import itertools

def neighbours(items, fill=None):
    before = itertools.chain([fill], items)
    after = itertools.chain(items, [fill]) #You could use itertools.zip_longest() later instead.
    next(after)
    for a, b, c in zip(before, items, after):
        yield [value for value in (a, b, c) if value is not fill]

像这样使用:

>>> items = [5, 1, 3, 8, 4]
>>> [sum(values)/len(values) for values in neighbours(items)]
[3.0, 3.0, 4.0, 5.0, 6.0]

那么这是如何工作的?我们为before和after值创建了一些额外的迭代器。我们使用itertools.chain分别为开头和结尾添加一个额外的值,以便我们在正确的时间获得正确的值(而不是用完项目)。然后我们将后一个项目推进到一个,将其放在正确的位置,然后循环,返回不是None的值。这意味着我们可以以非常自然的方式循环。

请注意,这需要一个列表,因为迭代器将耗尽。如果您需要它在迭代器上懒惰地工作,下面的示例使用itertools.tee()来完成这项工作:

def neighbours(items, fill=None):
    b, i, a = itertools.tee(items, 3)
    before = itertools.chain([fill], b)
    after = itertools.chain(a, [fill])
    next(a)
    for a, b, c in zip(before, i, after):
        yield [value for value in (a, b, c) if value is not fill]

答案 1 :(得分:0)

In [31]: lis=[5, 1, 3, 8, 4]

In [32]: new_lis=[lis[:2]]+[lis[i:i+3] for i in range(len(lis)-1)]

In [33]: new_lis
Out[33]: [[5, 1], [5, 1, 3], [1, 3, 8], [3, 8, 4], [8, 4]]

      #now using sum() ans len() on above list and using a list comprehension

In [35]: [sum(x)/float(len(x)) for x in new_lis]
Out[35]: [3.0, 3.0, 4.0, 5.0, 6.0]

或使用zip()

In [36]: list1=[lis[:2]] + zip(lis,lis[1:],lis[2:]) + [lis[-2:]]

In [37]: list1
Out[37]: [[5, 1], (5, 1, 3), (1, 3, 8), (3, 8, 4), [8, 4]]

In [38]: [sum(x)/float(len(x)) for x in list1]
Out[38]: [3.0, 3.0, 4.0, 5.0, 6.0]

答案 2 :(得分:0)

list_a = [5, 1, 3, 8, 4]
# Start list_b with the special case first element
list_b = [sum(list_a[:1]) / 2.0]
# Iterate over each remaining index in the list
for i in range(1, len(list_a - 1)):
    # Get the slice of the element and it's neighbors
    neighborhood = list_a[i-1:i+1]
    # Add the average of the element and it's neighbors
    # have to calculate the len of neighborhood to handle
    # last element special case
    list_b.append(sum(neighborhood) / float(len(neighborhood)))

答案 3 :(得分:0)

可以使用arcpy.AverageNearestNeighbor_stats

否则,如果你喜欢循环:

import numpy as np

listA= [5,1,3,8,4]
b = []

for r in xrange(len(listA)):
    if r==0 or r==len(listA):
        b.append(np.mean(listA[r:r+2]))
    else: 
        b.append(np.mean(listA[r-1:r+2]))

答案 4 :(得分:0)

看起来你有正确的想法。你的代码有点难以理解,将来尝试使用更具描述性的变量名称:)它使每个人都更容易。

这是我快速而又肮脏的解决方案:

def calcAverages(listOfNums):
    outputList = []
    for i in range(len(listOfNums)):
        if i == 0:
            outputList.append((listOfNums[0] + listOfNums[1]) / 2.)
        elif i == len(listOfNums)-1:
            outputList.append((listOfNums[i] + listOfNums[i-1]) / 2.)
        else:
            outputList.append((listOfNums[i-1] +
                            listOfNums[i] + 
                            listOfNums[i+1]) / 3.)
    return outputList

if __name__ == '__main__':
    listOne =  [5, 1, 3, 8, 4, 7, 20, 12]
    print calcAverages(listOne)

我选择了for循环而不是while。这并没有太大的区别,但我觉得语法更容易理解。

for i in range(len(listOfNums)):

我们创建一个循环,它将遍历输入列表的长度。

接下来我们处理两个“特殊”案例:列表的开头和结尾。

    if i == 0:
        outputList.append((listOfNums[0] + listOfNums[1]) / 2.)
    elif i == len(listOfNums)-1:
        outputList.append((listOfNums[i] + listOfNums[i-1]) / 2.)

因此,如果我们的索引为0,那么我们就在开头,因此我们添加当前索引的值0,以及下一个最高1,对其进行平均,并追加它到我们的输出列表。

如果我们的索引等于out列表的长度 - 1(我们使用-1,因为列表从0开始索引,而长度不是。没有-1,我们会得到IndexOutOfRange错误。)我们知道我们'关于最后一个元素。因此,我们获取该位置的值,将其添加到列表中前一个位置的值,最后将这些数字的平均值附加到输出列表中。

    else:
        outputList.append((listOfNums[i-1] +
                        listOfNums[i] + 
                        listOfNums[i+1]) / 3.)

最后,对于所有其他情况,我们只需获取当前索引处的值,以及紧接其上方和下方的值,然后将平均结果附加到输出列表中。