首页 > 解决方案 > Python 在一组序列中提取长度为 X 的常见模式

问题描述

假设我有以下内容:
data = ['ABCD', 'ABABC', 'BCAABCD']
我正在尝试创建一个函数,该函数使用Counter采用三个 argv,一个用于数据,第二个用于必须考虑此模式的序列数的最小比例,以及第三个是最大模式长度。

一个工作函数应该给我以下:

>>> check(data, 0.50, 2)
Counter({'A': 3, 'AB': 3, 'B': 3, 'BC': 3, 'C': 3, 'CD': 2, 'D': 2})

>>> check(data, 0.34, 4)
Counter({'A': 3, 'AB': 3, 'ABC': 3, 'ABCD': 2, 'B': 3, 'BC': 3, 'BCD': 2, 'C': 3, 'CD': 2, 'D': 2})

我真的迷失了这个东西,我只知道如何获得两个或多个字母的组合,如下所示:

Counter(combinations(data[0], 2)) & Counter(combinations(data[1], 2)) & Counter(combinations(data[2], 2))

而且我还知道如何获得所有数据元素中字母的总和:

Counter(data[0]) + Counter(data[1]) + Counter(data[2])

(奇怪的是,我无法像我想做的那样使用列表理解来做这个总和,因为一个错误说我不能在 'str' 和 'int' 之间做 '+'

如果你们可以' t 给我完整的代码,没问题,我只需要一些关于如何开始整个事情并获得逻辑的指导。

祝阅读我的整个事情的人度过愉快的一天 :)

标签: pythoncollectionssequencecounteritertools

解决方案


您可以使用递归生成器函数来获取合并子字符串的所有组合(长度<=最大),data并使用以下方法找到子字符串交集collections.defaultdict

from collections import defaultdict
data = ['ABCD', 'ABABC', 'BCAABCD']
def combos(d, l, c = []):
   if c:
      yield ''.join(c)
   if d and len(c) < l:
      yield from combos(d[1:], l, c+[d[0]])
      if not c:
          yield from combos(d[1:], l, c)

def check(d, p, l):
   _d = defaultdict(set)
   for i in d:
      for j in combos(i, l):
         _d[j].add(i)
   return {a:len(b) for a, b in _d.items() if len(b)/len(d) >= p}

print(check(data, 0.50, 2))
print(check(data, 0.34, 4))

输出:

{'A': 3, 'AB': 3, 'B': 3, 'BC': 3, 'C': 3, 'CD': 2, 'D': 2}
{'A': 3, 'AB': 3, 'ABC': 3, 'ABCD': 2, 'B': 3, 'BC': 3, 'BCD': 2, 'C': 3, 'CD': 2, 'D': 2}

推荐阅读