Python中字符串中子字符串的重叠计数

时间:2015-08-29 06:12:25

标签: python string count substring

我想找到字符串中子字符串的所有计数(重叠和非重叠)。 我找到了两个答案,其中一个是使用正则表达式,这不是我的意图,另一个比我需要的效率更高。 我需要这样的东西:

'ababaa'.count('aba') == 2

str.count()只计算简单的子串。我该怎么办?

8 个答案:

答案 0 :(得分:3)

def sliding(a, n):
    return (a[i:i+n] for i in xrange(len(a) - n + 1))

def substring_count(a, b):
    return sum(s == b for s in sliding(a, len(b)))

assert list(sliding('abcde', 3)) == ['abc', 'bcd', 'cde']    
assert substring_count('ababaa', 'aba') == 2

答案 1 :(得分:1)

这可以解决这个问题吗?

def count(string, substring):
    n = len(substring)
    cnt = 0
    for i in range(len(string) - n):
        if string[i:i+n] == substring:
            cnt += 1
    return cnt

print count('ababaa', 'aba') # 2

我不知道是否有更有效的解决方案,但这应该有用。

答案 2 :(得分:1)

在这里,使用re.finditer()是实现目标的最佳方式。

import re 

def get_substring_count(s, sub_s):
    return sum(1 for m in re.finditer('(?=%s)' % sub_s, s))

get_substring_count('ababaa', 'aba')
# 2 as response

答案 3 :(得分:1)

count = len(set([string.find('aba',x) for x in range(len(string)) if string.find('aba',x) >= 0]))

答案 4 :(得分:1)

这是您可以使用的功能:

def count(haystack, needle):
    return len([x for x in [haystack[i:j+1] for i in xrange(len(haystack)) for j in xrange(i,len(haystack))] if x == needle])

然后:

>>> count("ababaa", "aba")
2

答案 5 :(得分:1)

遍历切成薄片的字符串

def count_substring(string, sub_string):
    l = len(sub_string)
    n = len(string)
    count = sum(1 for i in range(n-l+1) if string[i:i+l].count(sub_string)>0 )
    return count

答案 6 :(得分:0)

蛮力方法就是

n = len(needle)
count = sum(haystack[i:i+n] == needle for i in range(len(haystack)-n+1))

(这是有效的,因为在Python中TrueFalse相当于数字10,用于大多数用途,包括数学)。

使用正则表达式可能是

count = len(re.findall(needle[:1]+"(?="+re.escape(needle[1:])+")",
                       haystack))

(即使用a(?=ba)代替aba来查找重叠匹配)

答案 7 :(得分:0)

要考虑的另一种方法是利用Counter容器。尽管对于较短的字符串,最快的答案是最快的,但如果您要在较长的字符串中搜索相对较短的子字符串,则Counter方法将占据优势。另外,如果您需要重构它以对同一主字符串执行多个子字符串计数查询,那么Counter方法将开始看起来更具吸引力

例如,搜索一个长度= 3的子字符串,使用timeit得到了以下结果;

主字符串长度/可接受的答案/应对方法

6个字符/ 4.1us / 7.4us

50个字符/ 24.4us / 25us

150个字符/ 70.7us / 64.9us

1500个字符/ 723us / 614us

from collections import Counter

def count_w_overlap(search_string, main_string):
    #Split up main_string into all possible overlap possibilities
    search_len = len(search_string)
    candidates = [main_string[i:i+search_len] for i in range(0, len(main_string) - search_len + 1)]
    #Create the Counter container
    freq_count = Counter(candidates)
    return freq_count[search_string]