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

时间:2018-04-10 07:29:23

标签: python python-3.x python-2.7 list count

给定模式[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次出现。

8 个答案:

答案 0 :(得分:4)

使用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))

答案 1 :(得分:2)

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)

答案 2 :(得分:2)

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

检查它是否包含模式

答案 3 :(得分:2)

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

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)))

希望这能解决你的问题。

答案 4 :(得分:2)

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

你可以改进它 - 请注意,如果你发现索引i'你可以跳过i + 1和i + 2并从i + 3开始检查(意思是 - 你可以检查是否有一个可以方便你搜索的子模式) 它花费O(n * m)

你可以使用向后卷积(称为模式匹配algorithem) 这需要花费O(n * log(n)),这是更好的

答案 5 :(得分:1)

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

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

    中的模式
    a_new = ''.join(map(str,a))
    
    pattern = ''.join(map(str,pattern))
    
    a_new.count(pattern)
    

答案 6 :(得分:1)

您可以将查找列表划分为您正在查看的模式大小的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中不是可哈希类型,因此不能用作dict键。

答案 7 :(得分:0)

您可以尝试范围方法:

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