0

问题:

给定一个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)
4

5 回答 5

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]

那么这是如何工作的呢?我们为之前和之后的值创建了一些额外的迭代器。我们使用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]
于 2012-10-11T14:36:39.280 回答
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)))
于 2012-10-11T14:30:34.633 回答
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]
于 2012-10-11T14:26:35.203 回答
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 list - 1 的长度(我们使用 -1 是因为列表从 0 开始索引,而长度不是。没有 -1,我们会得到一个 IndexOutOfRange 错误。)我们知道我们在最后一个元素。因此,我们取该位置的值,将其添加到列表中前一个位置的值中,最后将这些数字的平均值附加到输出列表中。

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

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

于 2012-10-11T14:39:20.830 回答
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]))
于 2012-10-11T14:34:51.940 回答