如果我有一个列表
a = [9,4,3,6,4,4,3,6,4]
如何检查相邻的两个元素是否相同?例如,对于索引为4和5的元素(它们都具有值4),这将为真。
pairs = zip(a, a[1:]) # Create tuples of neighbours
equals = map(lambda (x, y): x == y, pairs) # List of booleans which tells whether tuple elements are equal or not
hasEqualNeighbours = any(equals) # Is there a True boolean in the list?
或者导入eq
函数代替lambda,注意map可以同时迭代多个列表,所以不需要zip
:
from operator import eq
hasEqualNeigbours = any(map(eq, a, a[1:]))
如果你使用的是Python 2,你还可以使用from future_builtins import map
。这会使得map
成为一个惰性迭代器而不是构建整个列表对,从而节省内存,同时也可能减少运行时间。
any
会更加直观简单,而且使用带有map
的lambda
总是最糟糕的选择(如果使用C内置的map
可能还可以,否则,请使用生成器表达式)。但在这种情况下,map
可能更好,完全不需要使用zip
和operator.eq
:from operator import eq
,hasEqualNeighbors = any(map(eq, a, a[1:]))
。如果在Python 2上,则需要先执行from future_builtins import map
以获取基于生成器的map
(这样any
可以提前结束并在第一次检查时避免进一步检查)。 - ShadowRangerimport itertools
import operator
if any(map(operator.eq, a, itertools.islice(a, 1, None))):
print("There are equal neighbhors")
itertools.islice()
创建一个迭代器,它可以切片一个序列而不创建新的序列。 map()
通过使用 operator.eq()
检查每个时间是否相等,从而检查序列中的项目和后面的项目。
any()
然后迭代 map 并返回任意一个为 True
的结果。
对于 Python 2.x,我建议这样做:
import itertools
import operator
if any(itertools.imap(operator.eq, a, itertools.islice(a, 1, None))):
print("There are equal neighbhors")
由于Python 2.x中的map函数返回列表而不是迭代器。
itertools.groupby
:any(len(list(g)) > 1 for k, g in itertools.groupby(a))
这段代码非常直观,但是itertools
会将输入的可迭代对象分成值相等的块。我只需要查看是否有任何一个块具有多于1个元素。如果是,则存在相邻重复项。
这个算法的时间复杂度上限/平均时间复杂度为O(N),这是像这样的算法所能希望的最好结果。但是对于某些输入,它可以是O(1),因为它在找到匹配项时立即中断(例如,在可迭代对象的开头发现重复项)。
我相信这是最易读的版本:
>>> from itertools import izip
>>> any(first == second for first, second in izip(a, a[1:]))
True
any
的评估是惰性的。通过 izip
按需创建对。如果您使用的是 Python 3,则 zip
已经执行了 Python 2 中 izip
的功能。
解释:
>>> zip(a, a[1:])
[(9, 4), (4, 3), (3, 6), (6, 4), (4, 4), (4, 3), (3, 6), (6, 4)]
将创建相邻元素对的元组。传递给any
的是一个生成器表达式,用于检查这些元组中是否有两个相同的元素。
如果您想进一步优化内存效率,请像这样调用(i)zip
:
>>> it = iter(a)
>>> next(it, None)
9
>>> zip(a, it)
[(9, 4), (4, 3), (3, 6), (6, 4), (4, 4), (4, 3), (3, 6), (6, 4)]
a [1:]
。
a[i] == a[i+1]
吗? - OneCricketeerlen(a) - 1
作为范围的结尾。 - OneCricketeer