假设我想做以下事情:我有一个列表l
,在每一步我都想检查l[i]
和l[i+1]
之间的一些条件,如果满足,我会在l[i+1]
的基础上更新l[i]
并删除l[i+1]
,然后我会检查l[i]
和以前的l[i+2]
之间的条件,现在是新的l[i+1]
等等。如果在某一步条件不满足,我只是做i+=1
。
我的实现如下:
i = 0
while i < len(l):
if condition(l[i],l[i+1]):
l[i] = update(l[i+1])
del l[i+1]
else:
i += 1
不幸的是,len(l)
只计算一次,当检查while
子句时,只有i
发生变化,而不是len(l)
。因此,在某个时刻,如果我删除了一些元素,我会得到一个索引超出范围的错误。当我在迭代时插入列表的新成员时,会出现类似的问题。
首先,根据您的描述,我认为您想要del l[i+1]
,而不是del l[i]
在我看来,你的代码确实有效,我认为len(l)
每次都在更新,因为我的例子可以在我们希望的时候停止:
l = range(20)
i = 0
while i < len(l):
print i, len(l), l
if l[i] % 3 == 0:
l[i] = -l[i+1]
del l[i+1]
else:
i += 1
然而,如果您的条件在最后一步评估为true,那么您将遇到索引错误,如本例所示:
l = range(20)
i = 0
while i < len(l):
print i, len(l), l
if True:
l[i] = -l[i+1]
del l[i+1]
else:
i += 1
这是因为您检查了i < len(l)
,然后尝试访问索引i+1
。当你到达最后一个元素时,你想做什么?停下来?那么也许你需要这个:
i = 0
while i + 1 < len(l):
if condition(l[i],l[i+1]):
l[i] = update(l[i+1])
del l[i+1]
else:
i += 1
IMHO,有两种方法可以做到这一点:
-
使用Padraic Cunningham建议的第二个列表:
i = 0 l2 = [] while i < len(l) - 1: if insert_condition_before(l[i]): l2.append(for_insert_beore(l[i])) # insert before l[i] if condition(l[i],l[i+1]): l[i] = update(l[i+1]) i += 1 # skip l+1 l2.append(l[i]) i += 1 if insert_condition_after(l[i]): l2.append(for_insert_after(l[i])) # insert after l[i]
-
使用try-catch来确定阵列的末尾
i = 0 try: while True: if insert_condition_before(l[i]): l.insert(for_insert_before(l[i])) # insert before l[i] i += 1 if condition(l[i],l[i+1]): l[i] = update(l[i+1]) del l[i+1] i += 1 if insert_condition_after(l[i]): l.insert(for_insert_after(l[i])) # insert after l[i] i += 1 # if you do not want to analyse it again except IndexError: pass