如何在Python中找到字符串中多次出现的字符串?考虑一下:
>>> text = "Allowed Hello Hollow"
>>> text.find("ll")
1
>>>
因此ll
的第一次出现是预期的1。我如何找到它的下一个出现?
同样的问题对于列表有效。考虑:
>>> x = ['ll', 'ok', 'll']
如何找到所有ll
及其索引?
答案 0 :(得分:95)
使用正则表达式,您可以使用re.finditer
查找所有(非重叠)出现的内容:
>>> import re
>>> text = 'Allowed Hello Hollow'
>>> for m in re.finditer('ll', text):
print('ll found', m.start(), m.end())
ll found 1 3
ll found 10 12
ll found 16 18
或者,如果您不想要正则表达式的开销,您也可以重复使用str.find
来获取 next 索引:
>>> text = 'Allowed Hello Hollow'
>>> index = 0
>>> while index < len(text):
index = text.find('ll', index)
if index == -1:
break
print('ll found at', index)
index += 2 # +2 because len('ll') == 2
ll found at 1
ll found at 10
ll found at 16
这也适用于列表和其他序列。
答案 1 :(得分:21)
我认为你要找的是string.count
"Allowed Hello Hollow".count('ll')
>>> 3
希望这会有所帮助 注意:这仅捕获非重叠的出现
答案 2 :(得分:19)
对于列表示例,请使用理解:
>>> l = ['ll', 'xx', 'll']
>>> print [n for (n, e) in enumerate(l) if e == 'll']
[0, 2]
类似于字符串:
>>> text = "Allowed Hello Hollow"
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 10, 16]
这将列出相邻的“ll”运行,这可能是您想要的也可能不是:
>>> text = 'Alllowed Hello Holllow'
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 2, 11, 17, 18]
答案 3 :(得分:12)
FWIW,这里有一些我认为比poke's solution更整洁的非RE替代品。
第一个使用str.index
并检查ValueError
:
def findall(sub, string):
"""
>>> text = "Allowed Hello Hollow"
>>> tuple(findall('ll', text))
(1, 10, 16)
"""
index = 0 - len(sub)
try:
while True:
index = string.index(sub, index + len(sub))
yield index
except ValueError:
pass
第二项测试使用str.find
并使用-1
检查iter
的标记:
def findall_iter(sub, string):
"""
>>> text = "Allowed Hello Hollow"
>>> tuple(findall_iter('ll', text))
(1, 10, 16)
"""
def next_index(length):
index = 0 - length
while True:
index = string.find(sub, index + length)
yield index
return iter(next_index(len(sub)).next, -1)
要将这些函数中的任何一个应用于列表,元组或其他可迭代的字符串,您可以使用更高级别的函数 -one将一个函数作为一个函数它的论点 - 就像这样:
def findall_each(findall, sub, strings):
"""
>>> texts = ("fail", "dolly the llama", "Hello", "Hollow", "not ok")
>>> list(findall_each(findall, 'll', texts))
[(), (2, 10), (2,), (2,), ()]
>>> texts = ("parallellized", "illegally", "dillydallying", "hillbillies")
>>> list(findall_each(findall_iter, 'll', texts))
[(4, 7), (1, 6), (2, 7), (2, 6)]
"""
return (tuple(findall(sub, string)) for string in strings)
答案 4 :(得分:3)
对于您的列表示例:
In [1]: x = ['ll','ok','ll']
In [2]: for idx, value in enumerate(x):
...: if value == 'll':
...: print idx, value
0 ll
2 ll
如果您希望列表中包含“ll”的所有项目,您也可以这样做。
In [3]: x = ['Allowed','Hello','World','Hollow']
In [4]: for idx, value in enumerate(x):
...: if 'll' in value:
...: print idx, value
...:
...:
0 Allowed
1 Hello
3 Hollow
答案 5 :(得分:2)
>>> for n,c in enumerate(text):
... try:
... if c+text[n+1] == "ll": print n
... except: pass
...
1
10
16
答案 6 :(得分:1)
全面编程并通过在线教程完成工作。我也被要求这样做,但只使用我到目前为止学到的方法(基本上是字符串和循环)。不确定这是否会增加任何价值,我知道这不是你会怎么做的,但我得到了它的工作:
needle = input()
haystack = input()
counter = 0
n=-1
for i in range (n+1,len(haystack)+1):
for j in range(n+1,len(haystack)+1):
n=-1
if needle != haystack[i:j]:
n = n+1
continue
if needle == haystack[i:j]:
counter = counter + 1
print (counter)
答案 7 :(得分:1)
这段代码可能不是最短/最有效的,但它简单易懂
def findall(f, s):
l = []
i = -1
while True:
i = s.find(f, i+1)
if i == -1:
return l
l.append(s.find(f, i))
findall('test', 'test test test test')
# [0, 5, 10, 15]
答案 8 :(得分:0)
对于第一个版本,检查一个字符串:
def findall(text, sub):
"""Return all indices at which substring occurs in text"""
return [
index
for index in range(len(text) - len(sub) + 1)
if text[index:].startswith(sub)
]
print(findall('Allowed Hello Hollow', 'll'))
# [1, 10, 16]
无需导入 re
。这应该在线性时间内运行,因为它只循环遍历字符串一次(并在结束前停止,一旦没有足够的字符来容纳子字符串)。我个人也觉得它很有可读性。
请注意,这会发现重叠的事件:
print(findall('aaa', 'aa'))
# [0, 1]
答案 9 :(得分:0)
以下函数查找一个字符串在另一个字符串中的所有匹配项,同时通知每个匹配项出现的位置。
您可以使用下表中的测试用例调用该函数。您可以尝试将单词、空格和数字混合在一起。
该函数适用于重叠字符。
| theString | aString |
| -------------------------- | ------- |
| "661444444423666455678966" | "55" |
| "661444444423666455678966" | "44" |
| "6123666455678966" | "666" |
| "66123666455678966" | "66" |
Calling examples:
1. print("Number of occurrences: ", find_all("123666455556785555966", "5555"))
output:
Found in position: 7
Found in position: 14
Number of occurrences: 2
2. print("Number of occorrences: ", find_all("Allowed Hello Hollow", "ll "))
output:
Found in position: 1
Found in position: 10
Found in position: 16
Number of occurrences: 3
3. print("Number of occorrences: ", find_all("Aaa bbbcd$#@@abWebbrbbbbrr 123", "bbb"))
output:
Found in position: 4
Found in position: 21
Number of occurrences: 2
def find_all(theString, aString):
count = 0
i = len(aString)
x = 0
while x < len(theString) - (i-1):
if theString[x:x+i] == aString:
print("Found in position: ", x)
x=x+i
count=count+1
else:
x=x+1
return count
答案 10 :(得分:0)
不久前,我随机得到了这个主意。即使字符串重叠,也可以将While循环与字符串拼接和字符串搜索一起使用。
findin = "algorithm alma mater alison alternation alpines"
search = "al"
inx = 0
num_str = 0
while True:
inx = findin.find(search)
if inx == -1: #breaks before adding 1 to number of string
break
inx = inx + 1
findin = findin[inx:] #to splice the 'unsearched' part of the string
num_str = num_str + 1 #counts no. of string
if num_str != 0:
print("There are ",num_str," ",search," in your string.")
else:
print("There are no ",search," in your string.")
我是Python编程(实际上是任何语言的编程)的业余爱好者,并且不确定它可能还会遇到什么其他问题,但是我想它可以正常工作吗?
我想,如果需要,lower()也可以在其中使用。
答案 11 :(得分:0)
你也可以使用条件列表理解这样做:
string1= "Allowed Hello Hollow"
string2= "ll"
print [num for num in xrange(len(string1)-len(string2)+1) if string1[num:num+len(string2)]==string2]
# [1, 10, 16]
答案 12 :(得分:0)
我认为没有必要测试文本的长度;继续寻找,直到找不到任何东西。像这样:
<ion-list>
<button ion-item *ngFor="let branch of branchArray" (click)='goHome(branch)'>
<!-- Inner code here depending on your styling. -->
</button>
</ion-list>
答案 13 :(得分:0)
这个link解释了如何在O(n)中完成整个过程,并在python中包含一个解决方案。
如果你进一步向下移动到&#39; Suffix trees&#39;如果你有一个大字符串但想要在其中搜索1000个模式,你能够做同样的事情。
答案 14 :(得分:0)
也许不是Pythonic,但有点不言自明。它返回原始字符串中查找的单词的位置。
def retrieve_occurences(sequence, word, result, base_counter):
indx = sequence.find(word)
if indx == -1:
return result
result.append(indx + base_counter)
base_counter += indx + len(word)
return retrieve_occurences(sequence[indx + len(word):], word, result, base_counter)
答案 15 :(得分:0)
您可以拆分以获取相对位置,然后在列表中对连续数字求和,并同时添加(字符串长度*出现顺序)以获取所需的字符串索引。
>>> key = 'll'
>>> text = "Allowed Hello Hollow"
>>> x = [len(i) for i in text.split(key)[:-1]]
>>> [sum(x[:i+1]) + i*len(key) for i in range(len(x))]
[1, 10, 16]
>>>
答案 16 :(得分:0)
一个简单的迭代代码,它返回子字符串出现的索引列表。
def allindices(string, sub):
l=[]
i = string.find(sub)
while i >= 0:
l.append(i)
i = string.find(sub, i + 1)
return l
答案 17 :(得分:0)
这是我查找多次出现的函数。与此处的其他解决方案不同,它支持切片的可选开始和结束参数,就像str.index
一样:
def all_substring_indexes(string, substring, start=0, end=None):
result = []
new_start = start
while True:
try:
index = string.index(substring, new_start, end)
except ValueError:
return result
else:
result.append(index)
new_start = index + len(substring)
答案 18 :(得分:0)
call.answeredBy is null
该程序计算所有子串的数量,即使它们在不使用正则表达式的情况下重叠。但这是一个天真的实现,为了在最坏的情况下获得更好的结果,建议通过后缀树,KMP和其他字符串匹配数据结构和算法。
答案 19 :(得分:0)
这个版本应该是字符串长度的线性,并且只要序列不是太重复就应该没问题(在这种情况下你可以用while循环替换递归)。
def find_all(st, substr, start_pos=0, accum=[]):
ix = st.find(substr, start_pos)
if ix == -1:
return accum
return find_all(st, substr, start_pos=ix + 1, accum=accum + [ix])
bstpierre的列表理解是短序列的一个很好的解决方案,但看起来有二次复杂性,而且从未在我使用的长文本上完成。
findall_lc = lambda txt, substr: [n for n in xrange(len(txt))
if txt.find(substr, n) == n]
对于非平凡长度的随机字符串,这两个函数给出相同的结果:
import random, string; random.seed(0)
s = ''.join([random.choice(string.ascii_lowercase) for _ in range(100000)])
>>> find_all(s, 'th') == findall_lc(s, 'th')
True
>>> findall_lc(s, 'th')[:4]
[564, 818, 1872, 2470]
但二次版本慢了约300倍
%timeit find_all(s, 'th')
1000 loops, best of 3: 282 µs per loop
%timeit findall_lc(s, 'th')
10 loops, best of 3: 92.3 ms per loop