【问题标题】:Counting longest occurrence of repeated sequence in Python计算Python中重复序列的最长出现次数
【发布时间】:2010-04-18 22:00:59
【问题描述】:

计算字符串中某个字符最长连续重复的最简单方法是什么?例如,以下字符串中“b”的最长连续重复:

my_str = "abcdefgfaabbbffbbbbbbfgbb"

将是 6,因为其他连续重复更短(分别为 3 和 2。)如何在 Python 中做到这一点?

【问题讨论】:

    标签: python string


    【解决方案1】:

    一个正则表达式示例怎么样:

    import re
    my_str = "abcdefgfaabbbffbbbbbbfgbb"
    len(max(re.compile("(b+b)*").findall(my_str))) #changed the regex from (b+b) to (b+b)*
    # max([len(i) for i in re.compile("(b+b)").findall(my_str)]) also works
    

    编辑,我的 vs. interjays

    x=timeit.Timer(stmt='import itertools;my_str = "abcdefgfaabbbffbbbbbbfgbb";max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=="b")')
    x.timeit()
    22.759046077728271
    
    x=timeit.Timer(stmt='import re;my_str = "abcdefgfaabbbffbbbbbbfgbb";len(max(re.compile("(b+b)").findall(my_str)))')
    x.timeit()
    8.4770550727844238
    

    【讨论】:

    • +1 帮助部分恢复了本网站上正则表达式的价值——非常勇敢。
    【解决方案2】:

    这是一个单行:

    max(len(list(y)) for (c,y) in itertools.groupby(my_str) if c=='b')
    

    解释:

    itertools.groupby 将返回由连续相同字符组成的组,以及该组中所有项目的迭代器。对于每个这样的迭代器,len(list(y)) 将给出组中的项目数。取其中的最大值(对于给定字符)将给出所需的结果。

    【讨论】:

      【解决方案3】:

      这是我的代码,效率不高,但似乎有效:

      def LongCons(mystring):
          dictionary = {}
          CurrentCount = 0
          latestchar = ''
      
          for i in mystring:
              if i == latestchar:
                  CurrentCount += 1
                  if dictionary.has_key(i):
                      if CurrentCount > dictionary[i]:
                          dictionary[i]=CurrentCount
              else:
                  CurrentCount = 1
                  dictionary.update({i: CurrentCount})
                  latestchar = i
          k = max(dictionary, key=dictionary.get)
          print(k, dictionary[k])
          return
      

      【讨论】:

        【解决方案4】:

        这是我非常无聊、低效、直接的计数方法(interjay 的要好得多)。注意,我在这个没有解释器的小文本字段中写了这个,所以我没有测试它,我可能犯了一个非常愚蠢的错误,校对没有发现。

        my_str = "abcdefgfaabbbffbbbbbbfgbb"
        last_char = ""
        current_seq_len = 0
        max_seq_len = 0
        
        for c in mystr:
            if c == last_char:
                current_seq_len += 1
                if current_seq_len > max_seq_len:
                    max_seq_len = current_seq_len
            else:
                current_seq_len = 1
                last_char = c
        
        print(max_seq_len)
        

        【讨论】:

        • 您可能需要在循环中的某处更新last_char;除此之外,+1 提供了真正最简单的方法:这是程序员需要较少概念/技能的方法。顺便说一句,这不是“效率低下”:任何解决方案都需要查看字符串上的所有字符以提供正确的结果,因此其成本至少为 O(n):您的方法的时间成本为 O(n),所以它的效率相当高。轻微的效率改进是在 else: 块上更新 max_seq_len,因此它每个序列更新一次,而不是每个字符更新一次。
        • 好吧,忽略我关于更新 last_char 的观点,Ignacio 刚刚修复了它;)
        • 谢谢 Ignacio ;) (我的意思只是在你必须做多少打字方面效率低下)
        • 我可能会使用 max() 而不是 if,它不计算最长的“b”序列,而是任何字符(也许这在 ignacio 修复中中断了?) .无论如何,这比 IMNSHO 的 oneliners 要好得多。
        【解决方案5】:

        使用游程编码:

        import numpy as NP
        
        signal = NP.array([4,5,6,7,3,4,3,5,5,5,5,3,4,2,8,9,0,1,2,8,8,8,0,9,1,3])
        
        px, = NP.where(NP.ediff1d(signal) != 0)
        px = NP.r_[(0, px+1, [len(signal)])]
        # collect the run-lengths for each unique item in the signal
        rx = [ (m, n, signal[m]) for (m, n) in zip(px[:-1], px[1:]) if (n - m) > 1 ]
        
        # get longest:
        rx2 = [ (b-a, c) for (a, b, c) in rx ]
        rx2.sort(reverse=True)
        
        # returns: [(4, 5), (3, 8)], ie, '5' occurs 4 times consecutively, '8' occurs 3 times consecutively 
        

        【讨论】:

        • 不应该“if (n - m) > 1”是“if (n - m) >= 1”来检测长度为 1 的游程吗?
        • @carlo_hamalainen -- 没有。对检测 1 的“运行长度”并不真正感兴趣。
        猜你喜欢
        • 2017-12-24
        • 2021-07-16
        • 2018-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-09
        • 1970-01-01
        相关资源
        最近更新 更多