如何在字符串中查找 char 并获取所有索引?

我有个简单的代码:

def find(str, ch):
for ltr in str:
if ltr == ch:
return str.index(ltr)
find("ooottat", "o")

该函数只返回第一个索引。如果我更改返回值为 print,它将打印000。为什么会这样,有没有办法得到 0 1 2

141728 次浏览

这是因为 str.index(ch)将返回第一次出现 ch的索引。尝试:

def find(s, ch):
return [i for i, ltr in enumerate(s) if ltr == ch]

这将返回您需要的所有索引的列表。

另外,Hugh 的答案显示了一个生成器函数(如果索引列表变得很大,就会有所不同)。这个功能也可以通过改变 []()来调整。

def find_offsets(haystack, needle):
"""
Find the start of all (possibly-overlapping) instances of needle in haystack
"""
offs = -1
while True:
offs = haystack.find(needle, offs+1)
if offs == -1:
break
else:
yield offs


for offs in find_offsets("ooottat", "o"):
print offs

结果出来了

0
1
2

Lev 的答案 就是我要用的那个,不过这里有一些基于你的原始代码的东西:

def find(str, ch):
for i, ltr in enumerate(str):
if ltr == ch:
yield i


>>> list(find("ooottat", "o"))
[0, 1, 2]

我会选择 Lev,但是值得指出的是,如果你最终得到的是更复杂的搜索结果,那么使用 re.finditer 可能值得记住(但是 re 常常带来更多的麻烦而不是价值——但是有时候很方便知道)

test = "ooottat"
[ (i.start(), i.end()) for i in re.finditer('o', test)]
# [(0, 1), (1, 2), (2, 3)]


[ (i.start(), i.end()) for i in re.finditer('o+', test)]
# [(0, 3)]

你可以试试这个

def find(ch,string1):
for i in range(len(string1)):
if ch == string1[i]:
pos.append(i)
x = "abcdabcdabcd"
print(x)
l = -1
while True:
l = x.find("a", l+1)
if l == -1:
break
print(l)

根据经验,NumPy 阵列在使用 POD (普通旧数据)时的性能通常优于其他解决方案。字符串是 POD 和字符的一个例子。要查找字符串中只有一个字符的所有索引,NumPy ndarray 可能是最快的方法:

def find1(str, ch):
# 0.100 seconds for 1MB str
npbuf = np.frombuffer(str, dtype=np.uint8) # Reinterpret str as a char buffer
return np.where(npbuf == ord(ch))          # Find indices with numpy


def find2(str, ch):
# 0.920 seconds for 1MB str
return [i for i, c in enumerate(str) if c == ch] # Find indices with python

这是略微修改版本的 马克 · 兰塞姆的回答,工程如果 ch可以多于一个字符的长度。

def find(term, ch):
"""Find all places with ch in str
"""
for i in range(len(term)):
if term[i:i + len(ch)] == ch:
yield i

其它所有答案都有两个主要缺陷:

  1. 它们通过字符串执行 Python 循环,这个过程非常缓慢,或者
  2. 他们使用 numpy,这是一个相当大的附加依赖。
def findall(haystack, needle):
idx = -1
while True:
idx = haystack.find(needle, idx+1)
if idx == -1:
break
yield idx

这将遍历 haystack寻找 needle,始终从上一次迭代结束的地方开始。它使用内置的 str.find,这比逐个字符迭代 haystack要快得多。它不需要任何新的进口。

def find_idx(str, ch):
yield [i for i, c in enumerate(str) if c == ch]


for idx in find_idx('babak karchini is a beginner in python ', 'i'):
print(idx)

产出:

[11, 13, 15, 23, 29]

把所有的位置放在一条线上

word = 'Hello'
to_find = 'l'


# in one line
print([i for i, x in enumerate(word) if x == to_find])

为了美化由@Lev 和@Dark star 发布的五星级俏皮话:

word = 'Hello'
to_find = 'l'
print(", ".join([str(i) for i, x in enumerate(word) if x == to_find]))

这只是使索引数的分离更加明显。
结果是: 2, 3