我在python中有一个很大的数字列表,我想编写一个函数来查找列表中重复相同数字超过n次的部分。例如,如果n为3,则我的函数应返回以下示例的以下结果:
当应用于示例= [1,2,1,1,1,1,2,3]时,函数应该返回[(2,6)],因为示例[2:6]是一个包含所有的序列相同的价值。
当应用于example = [0,0,0,7,3,2,2,2,2,1]时,函数应该返回[(0,3),(5,9)],因为这两个例子[ 0:3]和示例[5:9]包含相同值的重复序列。
当应用于example = [1,2,1,2,1,2,1,2,1,2]时,函数应该返回[],因为没有三个或更多元素的序列都是相同的号。
我知道我可以编写一堆循环来获得我想要的东西,但这似乎效率低下,我想知道是否有更容易的选择来获得我想要的东西。
答案 0 :(得分:2)
使用itertools.groupby
和enumerate
:
>>> from itertools import groupby
>>> n = 3
>>> x = [1,2,1,1,1,1,2,3]
>>> grouped = (list(g) for _,g in groupby(enumerate(x), lambda t:t[1]))
>>> [(g[0][0], g[-1][0] + 1) for g in grouped if len(g) >= n]
[(2, 6)]
>>> x = [0,0,0,7,3,2,2,2,2,1]
>>> grouped = (list(g) for _,g in groupby(enumerate(x), lambda t:t[1]))
>>> [(g[0][0], g[-1][0] + 1) for g in grouped if len(g) >= n]
[(0, 3), (5, 9)]
要理解groupby:只要意识到每次迭代都会返回键的值,该值用于对iterable的元素进行分组,以及将遍历该组的新的lazy-iterable。
>>> list(groupby(enumerate(x), lambda t:t[1]))
[(0, <itertools._grouper object at 0x7fc90a707bd0>), (7, <itertools._grouper object at 0x7fc90a707ad0>), (3, <itertools._grouper object at 0x7fc90a707950>), (2, <itertools._grouper object at 0x7fc90a707c10>), (1, <itertools._grouper object at 0x7fc90a707c50>)]
答案 1 :(得分:1)
您可以按照当前算法在单个循环中执行此操作:
def find_pairs (array, n):
result_pairs = []
prev = idx = 0
count = 1
for i in range (0, len(array)):
if(i > 0):
if(array[i] == prev):
count += 1
else:
if(count >= n):
result_pairs.append((idx, i))
else:
prev = array[i]
idx = i
count = 1
else:
prev = array[i]
idx = i
return result_pairs
你可以这样调用这个函数:find_pairs(list, n)
。这是执行此任务的最有效方法,因为它具有复杂度O(len(array))。我觉得很容易理解,但如果你有任何疑问,请问。
答案 2 :(得分:0)
你可以用它。请注意,您的问题对于n的作用是不明确的。我在这里假设应该匹配一系列 n 相等的值。如果它至少应具有 n + 1 值,则将>=
替换为>
:
def monotoneRanges(a, n):
idx = [i for i, v in enumerate(a) if not i or a[i-1] != v] + [len(a)]
return [r for r in zip(idx, idx[1:]) if r[1] >= r[0]+n]
# example call
res = monotoneRanges([0,0,0,7,3,2,2,2,2,1], 3)
print(res)
输出:
[(0, 3), (5, 9)]