我有两个5个对象的数组
a = ['a','b','c','d','e','f','e','f']
b = ['a','b','d','f','e','f']
我想确定多个对象的重复模式及其出现情况,如
['a','b']:2
['e','f']:3
['f','e','f']:2
第一个序列['a','b']在a中出现一次,在b中出现一次,因此总计数为2.第二个序列['e','f']在a中出现两次,一次出现在b中,所以总数为3.第3个序列['f','e','f']在a中出现一次,在b中出现一次,所以总数为2.
在Python中有一个很好的方法吗?
对象的范围也是有限的。想知道是否有一个使用哈希表的有效解决方案?
答案 0 :(得分:2)
如果方法仅针对两个列表,则以下方法应该有效。我不确定这是否是最有效的解决方案。
在this blog post中给出了查找n-gram的一个很好的描述。
此方法提供最小长度并确定列表的重复序列可能具有的最大长度(最多为列表长度的一半)。
然后,我们通过组合各个列表的序列找到每个列表的所有序列。然后我们有一个每个序列及其计数的计数器。
最后,我们返回一个不止一次出现的所有序列的字典。
def find_repeating(list_a, list_b):
min_len = 2
def find_ngrams(input_list, n):
return zip(*[input_list[i:] for i in range(n)])
seq_list_a = []
for seq_len in range(min_len, len(list_a) + 1):
seq_list_a += [val for val in find_ngrams(list_a, seq_len)]
seq_list_b = []
for seq_len in range(min_len, len(list_b) + 1):
seq_list_b += [val for val in find_ngrams(list_b, seq_len)]
all_sequences = seq_list_a + seq_list_b
counter = {}
for seq in all_sequences:
counter[seq] = counter.get(seq, 0) + 1
filtered_counter = {k: v for k, v in counter.items() if v > 1}
return filtered_counter
如果您对任何事情不确定,请告诉我。
>>> list_a = ['a', 'b', 'c', 'd', 'e', 'f', 'e', 'f']
>>> list_b = ['a', 'b', 'd', 'f', 'e', 'f']
>>> print find_repeating(list_a, list_b)
{('f', 'e'): 2, ('e', 'f'): 3, ('f', 'e', 'f'): 2, ('a', 'b'): 2}
答案 1 :(得分:1)
当您提到您正在寻找高效解决方案时,我首先想到的是解决longest common subsequence problem的方法。但在你的情况下,我们确实需要枚举所有常见的子序列,以便我们可以对它们进行计数,因此动态编程解决方案不会这样做。这是我的解决方案。它肯定比SSSINISTER的解决方案更短(主要是因为我使用collections.Counter
类)。
#!/usr/bin/env python3
def find_repeating(sequence_a, sequence_b, min_len=2):
from collections import Counter
# Find all subsequences
subseq_a = [tuple(sequence_a[start:stop]) for start in range(len(sequence_a)-min_len+1)
for stop in range(start+min_len,len(sequence_a)+1)]
subseq_b = [tuple(sequence_b[start:stop]) for start in range(len(sequence_b)-min_len+1)
for stop in range(start+min_len,len(sequence_b)+1)]
# Find common subsequences
common = set(tup for tup in subseq_a if tup in subseq_b)
# Count common subsequences
return Counter(tup for tup in (subseq_a + subseq_b) if tup in common)
导致......
>>> list_a = ['a', 'b', 'c', 'd', 'e', 'f', 'e', 'f']
>>> list_b = ['a', 'b', 'd', 'f', 'e', 'f']
>>> print(find_repeating(list_a, list_b))
Counter({('e', 'f'): 3, ('f', 'e'): 2, ('a', 'b'): 2, ('f', 'e', 'f'): 2})
使用collections.Counter
的优势在于,您不仅无需生成实际代码进行迭代和计数,还可以访问所有dict
方法以及一些专门方法使用这些计数。