问题:
给定一个数字列表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)
答案 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.)
最后,对于所有其他情况,我们只需获取当前索引处的值,以及紧接其上方和下方的值,然后将平均结果附加到输出列表中。