【问题标题】:How To Get All The Contiguous Substrings Of A String In Python?如何在 Python 中获取字符串的所有连续子字符串?
【发布时间】:2014-04-23 13:56:33
【问题描述】:

这是我的代码,但是我想要一个更好的解决方案,你怎么看待这个问题?

def get_all_substrings(string):
  length = len(string)
  alist = []
  for i in xrange(length):
    for j in xrange(i,length):
      alist.append(string[i:j + 1]) 
  return alist

print get_all_substring('abcde')

【问题讨论】:

  • 在什么意义上更好,这个解决方案有什么问题?
  • 也许更快?或者没那么简单。
  • @user2357112,OP的母语显然不是英语,而且似乎OP在说“或者让这个功能变得更快并不是那么简单”。

标签: python string python-2.7 substring


【解决方案1】:

我能想到的唯一改进是,像这样使用列表理解

def get_all_substrings(input_string):
  length = len(input_string)
  return [input_string[i:j+1] for i in xrange(length) for j in xrange(i,length)]

print get_all_substrings('abcde')

你和我的时间比较

def get_all_substrings(string):
  length = len(string)
  alist = []
  for i in xrange(length):
    for j in xrange(i,length):
      alist.append(string[i:j + 1]) 
  return alist

def get_all_substrings_1(input_string):
  length = len(input_string)
  return [input_string[i:j + 1] for i in xrange(length) for j in xrange(i,length)]

from timeit import timeit
print timeit("get_all_substrings('abcde')", "from __main__ import get_all_substrings")
# 3.33308315277
print timeit("get_all_substrings_1('abcde')", "from __main__ import get_all_substrings_1")
# 2.67816185951

【讨论】:

  • 如果你正在做timeit,你可能会发现range 在这么小的范围内比xrange 快​​
  • @gnibbler 当我使用range 时,我得到的数字略大:(
  • @thefourtheye,不要难过 - 如果对小范围使用 xrange 不再受到惩罚(Python3 除外),这是一件好事
  • 我猜这个的时间复杂度是 O(n log n)?
【解决方案2】:

如果你不需要的话,你可以把它写成一个生成器,把所有的字符串一次性保存在内存中

def get_all_substrings(string):
    length = len(string)
    for i in xrange(length):
        for j in xrange(i + 1, length + 1):
            yield(string[i:j]) 

for i in get_all_substrings("abcde"):
    print i

如果你真的需要,你仍然可以列一个清单

alist = list(get_all_substrings("abcde"))

函数可以简化为返回一个生成器表达式

def get_all_substrings(s):
    length = len(s)
    return (s[i: j] for i in xrange(length) for j in xrange(i + 1, length + 1))

或者如果你不关心内存,当然你可以改变两个字符来返回一个列表

def get_all_substrings(s):
    length = len(s)
    return [s[i: j] for i in xrange(length) for j in xrange(i + 1, length + 1)]

【讨论】:

  • 这救了我,我遇到了内存错误,我做了一些搜索,找到了你的解决方案,它也解决了我的问题。谢谢。
【解决方案3】:

另一种解决方案:

def get_all_substrings(string):
   length = len(string)+1
   return [string[x:y] for x in range(length) for y in range(length) if string[x:y]]

print get_all_substring('abcde')

【讨论】:

    【解决方案4】:

    我从来不喜欢range(len(seq)),用枚举和只用索引值怎么样:

    def indexes(seq, start=0):
        return (i for i,_ in enumerate(seq, start=start))
    
    def gen_all_substrings(s):
        return (s[i:j] for i in indexes(s) for j in indexes(s[i:], i+1))
    
    def get_all_substrings(string):
        return list(gen_all_substrings(string))
    
    print(get_all_substrings('abcde'))
    

    【讨论】:

      【解决方案5】:

      使用itertools.permutations 生成所有可能的开始和结束索引对, 并仅过滤掉起始索引小于结束索引的那些。然后 使用这些对返回原始字符串的切片。

      from itertools import permutations
      
      def gen_all_substrings(s):
          lt = lambda pair: pair[0] < pair[1]
          index_pairs = filter(lt, permutations(range(len(s)+1), 2))
          return (s[i:j] for i,j in index_pairs)
      
      def get_all_substrings(s):
          return list(gen_all_substrings(s))
      
      print(get_all_substrings('abcde'))
      

      【讨论】:

        【解决方案6】:

        Python 3

        s='abc'
        list(s[i:j+1] for i in range (len(s)) for j in range(i,len(s)))
        
        ['a', 'ab', 'abc', 'b', 'bc', 'c']
        

        【讨论】:

        • 这重复了其他答案。您是否在 2-4 年前的前 2 个答案中添加了任何内容?
        【解决方案7】:

        可以用itertools.combinations简洁地完成

        from itertools import combinations
        
        def get_all_substrings_2(string):
            length = len(string) + 1
            return [string[x:y] for x, y in combinations(range(length), r=2)]
        

        【讨论】:

        • 这也比当前选择的答案性能要好得多。
        【解决方案8】:

        另一种使用二维矩阵方法的解决方案

        p = "abc"
        a = list(p)
        b = list(p)
        c = list(p)
        count = 0
        for i in range(0,len(a)):
               dump = a[i]
                    for j in range(0, len(b)):
                        if i < j:
                            c.append(dump+b[j])
                            dump = dump + b[j]  
        

        【讨论】:

          【解决方案9】:

          如果要获取按长度排序的子字符串:

          s = 'abcde'
          def allSubstrings(s: str) -> List[str]:
              length = len(s)
              mylist = []
              for i in range(1, length+1):
                  for j in range(length-i+1):
                      mylist.append(s[j:j+i])
              return mylist
          
          print(allSubstrings(s))
          
          ['a', 'b', 'c', 'd', 'e', 'ab', 'bc', 'cd', 'de', 'abc', 'bcd', 'cde', 'abcd', 'bcde', 'abcde']
          

          【讨论】:

            猜你喜欢
            • 2016-02-16
            • 1970-01-01
            • 2010-10-14
            • 2015-06-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-14
            相关资源
            最近更新 更多