如果我有一个清单
a = [9,4,3,6,4,4,3,6,4]
如何检查两个相邻元素是否相同? 例如,对于索引4和5处的元素(两者都具有值4)都是如此。
答案 0 :(得分:5)
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
成为一个惰性迭代器而不是构建整个对列表,从而节省了RAM和运行时间。
答案 1 :(得分:4)
这是 Python 3.x 关于内存和执行时间的有效方法。
import 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()
然后迭代地图,如果有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中的事实映射返回列表而不是迭代器。
答案 2 :(得分:1)
我可能会使用itertools.groupby
:
any(len(list(g)) > 1 for k, g in itertools.groupby(a))
代码非常简单,但itertools
将输入可迭代并将其分解为值相等的块。我只是想看看是否有任何块有超过1个元素。如果是,那么你有相邻的副本。
这有一个上限/平均时间复杂度O(N),这是你希望这样的算法最好的。但是对于某些输入,它可以是O(1),因为它一找到匹配就会短路(例如,在迭代的开头重复)。
答案 3 :(得分:0)
我相信这是最易阅读的版本:
>>> from itertools import izip
>>> any(first == second for first, second in izip(a, a[1:]))
True
any
的评估会很懒惰。配对由izip
按需创建。如果您使用的是Python 3,zip
已经完成了izip
在Python 2中所做的工作。
说明:
>>> 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:]
。