关于python for循环特别感兴趣的问题。工程程序通常需要先前或未来索引的值,例如:
for i in range(0,n):
value = 0.3*list[i-1] + 0.5*list[i] + 0.2*list[i+1]
等...
但是我更喜欢漂亮干净的python语法:
for item in list:
#Do stuff with item in list
或2d点数据列表:
for [x,y] in list:
#Process x, y data
我喜欢循环遍历列表而不明确使用索引来引用列表中的项目的概念。我想知道是否有一种干净的方法来抓取上一个或下一个项目而不循环索引(或者没有独立跟踪索引)?
编辑:
感谢Andrew Jaffe(以及代理Mark Byers)和gnibbler的简单,可扩展的示例。到目前为止,我还没有意识到itertools或nwise模块。 John Machin - 感谢非常复杂的例子。你在这个例子中付出了很多努力,显然我提出的一些递归算法不能生成与输入列表具有相同元素数量的列表,如果不使用显式索引则会出现问题。像这样的算法通常会出现在信号处理中。
答案 0 :(得分:4)
这是一个基于itertools成对代码的配方,它执行一般的n-wise分组:
import itertools
def nwise(iterable, n=2):
"s->(s_0,s_1, ..., s_n), (s_1,s_2,..., s_n+1), ... "
ntup = itertools.tee(iterable, n)
for i, item in enumerate(ntup):
for ii in range(i):
next(item, None)
return itertools.izip(*ntup)
可以这样使用:
>>> import nwise
>>> ll = range(10)
>>> for tup in nwise.nwise(ll,3): print tup
...
(0, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, 5)
(4, 5, 6)
(5, 6, 7)
(6, 7, 8)
(7, 8, 9)
[感谢Mark Byers对这个想法的回答]
答案 1 :(得分:2)
要访问元素和下一个元素,您可以使用recipe中显示的成对itertools documentation:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
这可以调整为允许访问三个相邻元素而不只是两个。
答案 2 :(得分:1)
>>> from itertools import islice, izip
>>> seq = range(10)
>>> for x,y,z in izip(*(islice(seq,i,None) for i in range(3))):
... print x,y,z
...
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
这可以简单地扩展到3项以上。
如果你需要它可以使用任何迭代,安德鲁的答案是合适的,或者你可以这样做
>>> from itertools import izip, islice, tee
>>> seq=(x for x in range(10))
>>> for x,y,z in izip(*(islice(j,i,None) for i,j in enumerate(tee(seq,3)))):
... print x,y,z
...
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
答案 3 :(得分:0)
如果你想使用拉链,这里是如何不做(填充,不必要)以及如何不检查(填充x 2.5),纠正这些缺陷。
vector = [2**i for i in range(1,6)]
print "vector", vector
value = []
for i in range(1,len(vector)-1):
value.append(0.3*vector[i-1] + 0.5*vector[i] + 0.2*vector[i+1])
print "value", len(value), value
value2=[0.3*before + 0.5* this + 0.2 * after
for before,this,after in zip(vector,vector[1:]+[0], vector[2:]+[0,0])
]
# above +[0] and +[0,0] needlessly extend the answer by two items
print "value2", len(value2), value2
print "bad check bad values", not any([x-y for x,y in zip(value,value2) if x-y > 1e-7])
# the bad check doesn't check for length
# the bad check doesn't use abs(actual - expected)
# the bad check has a unnecessary if test in it
# the bad check uses a list comprehension when a generator would do
print "good check bad values", (
len(value2) == len(value)
and
not any(abs(x-y) > 1e-7 for x,y in zip(value,value2))
)
value2=[0.3*before + 0.5* this + 0.2 * after
for before,this,after in zip(vector,vector[1:], vector[2:])
]
print "fixed value2", len(value2), value2
print "good check good values", (
len(value2) == len(value)
and
not any(abs(x-y) > 1e-7 for x,y in zip(value,value2))
)