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

86

我有一些简单的代码:

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

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


8
请注意,不要将“str”用作变量名,因为它是Python中的现有关键字。 - Silas Ray
3
str 不是关键字,而只是一个内置名称(无法用作变量名的关键字),以上为翻译内容。 - Wooble
5
好的,没问题。这并不改变使用它作为变量名是不好的实践这一事实。 :) - Silas Ray
13个回答

137

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

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

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

附注:Hugh的答案展示了一个生成器函数(如果索引列表变得很大会有差别)。这个函数也可以通过将[]更改为()进行调整。


1
使用 enumerate,好的解决方案! - malana
1
ch必须是单个字符吗?我尝试使用ch = '&#'s = Народ,但没有成功。 - Chris Nielsen
2
@ChrisNielsen确实,这对于更长的子字符串是行不通的,因为enumerates中迭代字符,因此只有当ch是单个字符时,ltr == ch才可能为True - Lev Levitsky

26

我会选择Lev,但值得指出的是,如果你需要进行更复杂的搜索,考虑使用re.finditer可能是值得注意的(但是正则表达式通常会带来更多的麻烦 - 但有时候知道也很方便)

我会选择Lev,但值得指出的是,如果你需要进行更复杂的搜索,考虑使用re.finditer可能是值得注意的(但是正则表达式通常会带来更多的麻烦 - 但有时候知道也很方便)

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

19

Lev的答案是我会使用的,不过这里有一些基于你原来代码的东西:

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

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

16
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

4

只需一行代码获取所有位置信息

word = 'Hello'
to_find = 'l'

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

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

1
作为一个经验法则,当处理POD(Plain Old Data)时,NumPy数组常常比其它解决方案表现更优。字符串和字符都是POD的例子。若要在字符串中找到所有一个字符的索引,NumPy ndarrays可能是最快的方法:
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

1
我认为这是最简单的方法:
def find(ch, string1):
    return [i for i in range(len(string1)) if string1[i]==ch]


没有外部库,只用简单的Python =)

0
x = "abcdabcdabcd"
print(x)
l = -1
while True:
    l = x.find("a", l+1)
    if l == -1:
        break
    print(l)

4
虽然这段代码可能回答了问题,但提供解释它如何以及为什么解决问题可以增加其长期价值。 - L_J
@Arvind:欢迎来到Stackoverflow。您介意扩展一下您的答案,以便其他程序员能够理解它如何帮助解决问题吗? - Nagama Inamdar

0

这是 Mark Ransom 的答案的稍微修改版本,适用于 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

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