Python有string.find()和string.rfind()来获取字符串中子字符串的索引。

我想知道是否有像string.find_all()这样的东西可以返回所有找到的索引(不仅是从开始的第一个索引,还是从结束的第一个索引)。

例如:

string = "test test test test"

print string.find('test') # 0
print string.rfind('test') # 15

#this is the goal
print string.find_all('test') # [0,5,10,15]

要统计出现次数,请参见计算字符串中子字符串出现的次数。


当前回答

没有简单的内置字符串函数来做你正在寻找的事情,但你可以使用更强大的正则表达式:

import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]

如果你想找到重叠的匹配,lookahead会这样做:

[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]

如果你想要一个没有重叠的反向查找-all,你可以将正负前向组合成这样的表达式:

search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]

red .finditer返回一个生成器,因此您可以将上面的[]更改为()以获得一个生成器,而不是一个列表,如果您只迭代一次结果,这将更有效。

其他回答

当在一份文件中寻找大量的关键词时,使用flash文本

from flashtext import KeywordProcessor
words = ['test', 'exam', 'quiz']
txt = 'this is a test'
kwp = KeywordProcessor()
kwp.add_keywords_from_list(words)
result = kwp.extract_keywords(txt, span_info=True)

在大量搜索词列表上,Flashtext比正则表达式运行得更快。

查找给定字符串中某个字符的所有出现次数,并作为字典返回 例如:你好 结果: {'h':1, 'e':1, 'l':2, 'o':1}

def count(string):
   result = {}
   if(string):
     for i in string:
       result[i] = string.count(i)
     return result
   return {}

否则你就像这样

from collections import Counter

   def count(string):
      return Counter(string)

对于非重叠匹配,可以使用re.finditer()。

>>> import re
>>> aString = 'this is a string where the substring "is" is repeated several times'
>>> print [(a.start(), a.end()) for a in list(re.finditer('is', aString))]
[(2, 4), (5, 7), (38, 40), (42, 44)]

但不适用于:

In [1]: aString="ababa"

In [2]: print [(a.start(), a.end()) for a in list(re.finditer('aba', aString))]
Output: [(0, 3)]

这不完全是OP要求的,但你也可以使用split函数来获得所有子字符串不出现的列表。OP没有指定代码的最终目标,但如果您的目标是删除子字符串,那么这可能是一个简单的一行程序。对于更大的字符串,可能有更有效的方法来做到这一点;在这种情况下,正则表达式更可取

# Extract all non-substrings
s = "an-example-string"
s_no_dash = s.split('-')
# >>> s_no_dash
# ['an', 'example', 'string']

# Or extract and join them into a sentence
s_no_dash2 = ' '.join(s.split('-'))
# >>> s_no_dash2
# 'an example string'

我简单浏览了一下其他的答案,如果这个已经在上面了,我很抱歉。

这里有一个(非常低效的)方法来获得所有(即重叠)匹配:

>>> string = "test test test test"
>>> [i for i in range(len(string)) if string.startswith('test', i)]
[0, 5, 10, 15]