【问题标题】:How to count number of substrings in python, if substrings overlap?如果子字符串重叠,如何计算python中子字符串的数量?
【发布时间】:2018-08-23 21:23:42
【问题描述】:

count() 函数返回子字符串在字符串中出现的次数,但如果字符串重叠则失败。

假设我的输入是:

^_^_^-_-

我想知道^_^在字符串中出现了多少次。

mystr=input()
happy=mystr.count('^_^')
sad=mystr.count('-_-')
print(happy)
print(sad)

输出是:

1
1

我期待:

2
1

我怎样才能达到预期的效果?

【问题讨论】:

    标签: python-3.x substring


    【解决方案1】:

    新版本

    您无需使用正则表达式编写任何显式循环即可解决此问题。正如@abhijith-pk's answer 巧妙地建议的那样,您可以只搜索第一个字符,其余的被放置在正向前瞻中,这将允许您进行重叠匹配:

    def count_overlapping(string, pattern):
        regex = '{}(?={})'.format(re.escape(pattern[:1]), re.escape(pattern[1:]))
        # Consume iterator, get count with minimal memory usage
        return sum(1 for _ in re.finditer(regex, string))
    

    [IDEOne Link]

    [:1][1:] 用于索引允许函数无需特殊处理即可处理空字符串,而将[0][1:] 用于索引则不会。

    旧版

    您始终可以使用str.find 允许您指定起始索引的事实编写自己的例程。此例程效率不高,但应该可以:

    def count_overlapping(string, pattern):
        count = 0
        start = -1
        while True:
            start = string.find(pattern, start + 1)
            if start < 0:
                return count
            count += 1
    

    [IDEOne Link]

    用法

    两个版本返回相同的结果。示例用法是:

    >>> mystr = '^_^_^-_-'
    >>> count_overlapping(mystr, '^_^')
    2
    >>> count_overlapping(mystr, '-_-')
    1
    >>> count_overlapping(mystr, '')
    9
    >>> count_overlapping(mystr, 'x')
    0
    

    请注意,空字符串被发现len(mystr) + 1 次。我认为这在直觉上是正确的,因为它有效地介于每个角色之间和周围。

    【讨论】:

      【解决方案2】:

      您可以使用正则表达式来获得快速而肮脏的解决方案:

      import re
      mystr='^_^_^-_-'
      print(len(re.findall('\^(?=_\^)',mystr)))
      

      【讨论】:

      • 这太棒了。搜索第一个字符,对其余字符进行正向前瞻。我可以窃取并概括它吗?
      • @MadPhysicist 是的,请并感谢您很好地解释它:)
      • 我知道其中一位正则表达式忍者会出来并发布更好的答案:-)
      • @Abhijithpk。请参阅我的答案的更新。似乎像我之前发布的废话一样工作,但更优雅。谢谢你给我看这个
      • @AyushGoyal 看看 MadPhysicist 的更新答案,他正在解释积极前瞻的工作原理,他使用 re.escape 来避免转义正则表达式特殊字符,例如 ^ 而不是我粗略的反斜杠转义序列跨度>
      【解决方案3】:

      你需要这样的东西

      def count_substr(string,substr):
          n=len(substr)
          count=0
          for i in range(len(string)-len(substr)+1):
              if(string[i:i+len(substr)] == substr):      
                  count+=1
          return count
      
      mystr=input()
      print(count_substr(mystr,'121'))
      

      输入:12121990

      输出:2

      【讨论】:

      • 这是一个功能齐全的解决方案,但它有许多低效率的地方。主要是string[i:i+len(substr)]每次都会创建一个新的字符串对象。
      • 完全同意你的看法。这不是一个有效的解决方案,但只有我能想到的。会明显改善:-)
      • 功能齐全,所以+1。我真的不认为我的更好,但我也想不出更好的方法:)
      • 我特别喜欢我们在没有任何特殊处理的空模式下得到相同的结果。
      • 我认为这样做绝对是理想的:) 我什至在我的回答中提到了它。
      猜你喜欢
      • 1970-01-01
      • 2014-11-01
      • 2015-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多