mylist="'a','b','c'"
count=0
i=0
while count< len(mylist):
if mylist[i]==mylist[i+1]:
print mylist[i]
count +=1
i +=1
错误:
File "<string>", line 6, in <module>
IndexError: string index out of range
我假设当它到达最后一个(第n个)元素时,它找不到n + 1来比较它,所以它给了我一个错误。
有趣的是,我认为我之前已经完成了这个并且没有在更大的列表中出现这个问题:这是一个例子(由Raymond Hettinger负责修复它)
list=['a','a','x','c','e','e','f','f','f']
i=0
count = 0
while count < len(list)-2:
if list[i] == list[i+1]:
if list [i+1] != list [i+2]:
print list[i]
i+=1
count +=1
else:
print "no"
count += 1
else:
i +=1
count += 1
为了按照我尝试的方式浏览列表,是否有任何修复以便我不会“超出范围?”我计划在一个非常大的列表中实现它,例如,我必须检查“list [i] == list [i + 16]”。在将来,我想添加条件,如“if int(mylist [i + 3]) - int(mylist [i + 7])&gt; 10:newerlist.append [mylist [i]”。所以我解决这个问题很重要。
我考虑过插入一个break语句,但是没有成功。
我知道这不是最有效的,但我正处于我最了解的地步。
答案 0 :(得分:5)
所以听起来你正试图在各种固定偏移量下比较列表中的元素。也许这样的事情可以帮助你:
for old, new in zip(lst, lst[n:]):
if some_cond(old, new):
do_work()
lst[n:]
返回lst的副本,从第n个开头(介意0索引)元素
>>> lst = [1,2,2,3];
>>> lst[1:]
[2,2,3]
zip(l1, l2)
创建一个新的元组列表,每个列表中有一个元素
>>> zip(lst, lst[1:])
[(1, 2), (2, 2), (2, 3)]
请注意,只要列表用完,它就会停止。在这种情况下,偏移列表首先用完。
对于元组列表,你可以在循环变量中直接“upack”,所以
for old, new in zip(lst, lst[1:])
给出你想要的元素循环(列表中的连续元素对)
答案 1 :(得分:1)
总的来说,如果你想要向前看一定数量的地方,你可以做一些事情:
在循环检查(即计数&lt; length)中,您需要检查最大字段。所以在你的例子中,你想要16个空格。这意味着您需要检查计数&lt; (长度 - 16)。缺点是你的最后一个元素(最后16个)不会被迭代。
检查循环内部以确保索引适用。也就是说,在每个if语句中以:if(I + 16&lt; length&amp;&amp; logic_you_want_to_check)开头。这将允许您继续循环,但是当逻辑因为超出界限而失败时,您将不会出错。
注意 - 这可能不是你想要的,但是为了完整性而添加它。包裹你的逻辑。这只有在考虑环绕时才有效。如果你真的想要检查当前索引之前的第16个索引(也许就像某个行中的某个地方),那么环绕并不适合。但是如果不需要那种逻辑,并且想要以圆形模式对值进行建模,则可以对索引进行模数化。那就是:如果array [i] == array [(i + 16)%length(array)]将检查前面的16或者回绕到数组的前面。
答案 2 :(得分:-1)
编辑:
是的,随着OP中的新信息,这变得更加简单。使用the itertools
grouper()
recipe将每个人的数据分组为元组:
import itertools
def grouper(iterable, n, fillvalue=None):
"""Collect data into fixed-length chunks or blocks"""
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
data = ['John', 'Sally', '5', '10', '11', '4', 'John', 'Sally', '3', '7', '7', '10', 'Bill', 'Hallie', '4', '6', '2', '1']
grouper(data, 6)
现在您的数据如下:
[
('John', 'Sally', '5', '10', '11', '4'),
('John', 'Sally', '3', '7', '7', '10'),
('Bill', 'Hallie', '4', '6', '2', '1')
]
相比之下,哪个应该易于使用。
旧答案:
如果您需要制作更多任意链接,而不仅仅是检查连续值:
def offset_iter(iterable, n):
offset = iter(iterable)
consume(offset, n)
return offset
data = ['a', 'a', 'x', 'c', 'e', 'e', 'f', 'f', 'f']
offset_3 = offset_iter(data, 3)
for item, plus_3 in zip(data, offset_3): #Naturally, itertools.izip() in 2.x
print(item, plus_3) #if memory usage is important.
当然,您可能希望使用语义上有效的名称。这种方法的优点是它适用于任意迭代,而不仅仅是列表,并且有效且可读,没有索引的任何丑陋,低效的迭代。如果您需要在偏移值用完后继续检查(例如,对于其他条件),请使用itertools.zip_longest()
(2.x中的itertools.izip_longest()
)。
使用the consume()
recipe from itertools
。
import itertools
import collections
def consume(iterator, n):
"""Advance the iterator n-steps ahead. If n is none, consume entirely."""
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(itertools.islice(iterator, n, n), None)
但是,如果在这种情况下需要重新检查数据结构,我会非常怀疑。
原始答案:
我不确定你的目标是什么,但从我收集的内容中你可能想要itertools.groupby()
:
>>> import itertools
>>> data = ['a', 'a', 'x', 'c', 'e', 'e', 'f', 'f', 'f']
>>> grouped = itertools.groupby(data)
>>> [(key, len(list(items))) for key, items in grouped]
[('a', 2), ('x', 1), ('c', 1), ('e', 2), ('f', 3)]
当有(任意大的)重复项目运行时,您可以使用它来计算。值得注意的是,您可以为itertools.groupby()
提供一个key
参数,该参数将根据您想要的任何因素对它们进行分组,而不仅仅是相等。
答案 3 :(得分:-2)
如果您遵守"Practicality beats purity":
for idx, element in enumerate(yourlist[n:]):
if yourlist[idx] == yourlist[idx-n]
...
如果你不关心记忆效率,请选择第二个答案。如果你想要最纯粹的答案,那就选择Lattyware吧。