繁体   English   中英

计算Python中列表中模式的出现次数

[英]Count the number of occurences of a pattern in a list in Python

给定模式[1,1,0,1,1] ,以及长度为100的二进制列表, [0,1,1,0,0,...,0,1] 我想计算此列表中此模式的出现次数。 是否有一种简单的方法可以在不需要使用变量跟踪每个索引处的每个项目的情况下执行此操作?

注意这样的事情, [...,1, 1, 0, 1, 1, 1, 1, 0, 1, 1,...,0]可能会发生,但这应该算作2次出现。

使用join将列表转换为字符串。 然后做:

text.count(pattern)

如果需要计算重叠匹配,则必须使用正则表达式匹配或定义自己的函数。

编辑这是完整的代码:

def overlapping_occurences(string, sub):
    count = start = 0
    while True:
        start = string.find(sub, start) + 1
        if start > 0:
            count+=1
        else:
            return count

given_list = [1, 1, 0, 1, 1, 1, 1, 0, 1, 1]
pattern = [1,1,0,1,1]

text = ''.join(str(x) for x in given_list)
print(text)
pattern = ''.join(str(x) for x in pattern)
print(pattern)
print(text.count(pattern)) #for no overlapping
print(overlapping_occurences(text, pattern))
l1 = [1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]
l1str = str(l1).replace(" ", "").replace("[", "").replace("]", "")

l3 = [1, 1, 0, 1, 1]
l3str = str(l3).replace(" ", "").replace("[", "").replace("]", "")


l1str = l1str.replace(l3str, "foo")
foo = l1str.count("foo")
print(foo)
from collections import Counter

a = [1,1,0,1,1]
b = [1,1,0,1,1,1,1,0,1,1]

lst = list()
for i in range(len(b)-len(a)+1):
    lst.append(tuple(b[i:i+len(a)]))

c = Counter(lst)
print c[tuple(a)]

产量

2

循环可以写成一行,例如,对于更“干净”但不太了解的代码

lst = [tuple(b[i:i+len(a)]) for i in range(len(b)-len(a)+1)]

注意,我正在使用元组,因为它们是不可变对象,可以进行哈希处理

你也可以使用哈希函数并创建自己的哈希方法,例如每个var多个,其中10个提升到他的位置,例如

[1,0,1] = 1 * 1 + 0 * 10 + 1 * 100 = 101

这样你可以在列表上进行一次传递,并检查它是否包含模式,只需检查if sub_list == 101

我认为一个简单的正则表达式就足够了:

def find(sample_list):
    list_1 = [1,1,0,1,1]
    str_1 = str(list_1)[1:-1]
    print len(re.findall(str_1, str(sample_list)))

希望这能解决你的问题。

你总是可以使用天真的方式:for循环列表的切片(如在第i个索引处开始并以i + [模式的长度]结束的切片)。

并且你可以改进它 - 请注意,如果你在索引i'中发现了一个'你可以跳过i + 1和i + 2并从i + 3和向后检查(意思是 - 你可以检查是否有一个子模式将会便于搜索)它的成本为O(n * m)

你可以使用向后卷积(称为模式匹配algorithem)这个花费O(n * log(n))哪个更好

您可以使用以下两个步骤解决它:

  • 将列表中的所有元素组合在一个字符串中
  • 使用python count函数匹配字符串中的模式

     a_new = ''.join(map(str,a)) pattern = ''.join(map(str,pattern)) a_new.count(pattern) 

您可以将查找列表划分为您正在查看的模式大小的chucks。 您可以使用涉及itertools.islice简单配方来实现此目的,以生成滑动窗口迭代器

>>> from itertools import islice

>>> p = [1,1,0,1,1]
>>> l = [0,1,1,0,0,0,1,1,0,1,1,1,0,0,1]
>>> [tuple(islice(l,k,len(p)+k)) for k in range(len(l)-len(p)+1)]

这将为您提供如下输出:

>>> [(0, 1, 1, 0, 0), (1, 1, 0, 0, 0), (1, 0, 0, 0, 1), (0, 0, 0, 1, 1), (0, 0, 1, 1, 0), (0, 1, 1, 0, 1), (1, 1, 0, 1, 1), (1, 0, 1, 1, 1), (0, 1, 1, 1, 0), (1, 1, 1, 0, 0), (1, 1, 0, 0, 1)]

现在您可以使用collections.Counter按顺序计算每个子列表的出现次数

 >>> from collections import Counter
 >>> c = Counter([tuple(islice(l,k,len(p)+k)) for k in range(len(l)-len(p)+1)])
 >>> c 
 >>> Counter({(0, 1, 1, 0, 1): 1, (1, 1, 1, 0, 0): 1, (0, 0, 1, 1, 0): 1, (0, 1, 1, 1, 0): 1, (1, 1, 0, 0, 0): 1, (0, 0, 0, 1, 1): 1, (1, 1, 0, 1, 1): 1, (0, 1, 1, 0, 0): 1, (1, 0, 1, 1, 1): 1, (1, 1, 0, 0, 1): 1, (1, 0, 0, 0, 1): 1})

要获取所需序列的频率,请使用

 >>> c.get(tuple(p),0)
 >>> 1

注意我已经将tuple作为dict键使用,因为list在python中不是hashable类型,因此不能用作dict键。

您可以尝试范围方法:

pattern_data=[1,1,0,1,1]
data=[1,1,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1]

count=0
for i in range(0,len(data),1):
    if data[i:i+len(pattern_data)]==pattern_data:
        print(i,data[i:i+len(pattern_data)])
        j+=1

print(count)

输出:

0 [1, 1, 0, 1, 1]
15 [1, 1, 0, 1, 1]
20 [1, 1, 0, 1, 1]
35 [1, 1, 0, 1, 1]
40 [1, 1, 0, 1, 1]
52 [1, 1, 0, 1, 1]
55 [1, 1, 0, 1, 1]
60 [1, 1, 0, 1, 1]
75 [1, 1, 0, 1, 1]
80 [1, 1, 0, 1, 1]
95 [1, 1, 0, 1, 1]
11

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM