如何在Python中获取字符串的所有连续子串?

42

这是我的代码,但我希望有更好的解决方案,你对这个问题有什么想法吗?

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

1
更好的方面是什么?这个解决方案有什么问题? - thefourtheye
也许更快?或者不那么简单。 - lqhcpsgbl
@user2357112,OP的母语显然不是英语,而且似乎OP在说“或许要让这个函数更快并不是那么简单”。 - sleblanc
9个回答

48

我能想到的唯一改进就是像这样使用列表推导式:

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,可能会发现对于这么小的范围,rangexrange更快。 - John La Rooy
@gnibbler 当我使用range时,得到的数字会稍微大一些 :( - thefourtheye
@thefourtheye,不要难过——如果使用xrange处理小范围的数据不再受到惩罚(Python3除外),这是一件好事。 - John La Rooy
我猜这个的时间复杂度是 O(n log n)? - Tian

17

可以使用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)]

2
这比目前选择的答案更具性能。 - jidicula

10

如果您不需要,可以将其编写为生成器以节省一次性存储所有字符串的内存空间。

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

2
这救了我,我遇到了内存错误,进行了一些搜索,发现了你的解决方案,它也解决了我的问题。谢谢。 - Sonny Parlin

7

我从未喜欢过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'))

4

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']

4
这个答案与其他回答重复。你在两到四年前的前两个答案中加入了什么内容吗? - jpp

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

0

另一种解决方案:

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

0

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

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]  

0
如果您想按长度排序获取子字符串:
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']

1
推导式比循环快得多。 - MatBailie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接