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

How to find char in string and get all the indexes?

提问人:William Xing 提问时间:6/20/2012 最后编辑:ParadoxWilliam Xing 更新时间:11/17/2023 访问量:159985

问:

我得到了一些简单的代码:

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

python 字符串

评论

8赞 Silas Ray 6/20/2012
可以这么说,不要使用 str 作为变量名,因为它是 Python 中的现有关键字。
3赞 Wooble 6/20/2012
@sr2222:不是关键字,只是一个内置名称(关键字不能用作变量名称)str
5赞 Silas Ray 6/20/2012
@Wooble 很公平。不会改变将其用作变量名称是不好的做法这一事实。:)

答:

141赞 Lev Levitsky 6/20/2012 #1

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

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

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

P.S. Hugh 的回答显示了一个生成器函数(如果索引列表可以变大,它会有所不同)。也可以通过将此功能更改为 来调整此功能。[]()

评论

1赞 malana 10/21/2016
使用,不错的解决方案!enumerate
1赞 Chris Nielsen 7/13/2017
ch 必须是单个字符吗?我尝试过使用它,但没有用。ch = '&#'s = Народ
2赞 Lev Levitsky 7/13/2017
@ChrisNielsen确实,这不适用于较长的子字符串,因为遍历 中的字符,因此只能是 if 是单个字符。enumeratesltr == chTruech
16赞 Hugh Bothwell 6/20/2012 #2
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
19赞 Mark Ransom 6/20/2012 #3

Lev 的答案是我会使用的答案,但是这里有一些基于您的原始代码的内容:

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

>>> list(find("ooottat", "o"))
[0, 1, 2]
26赞 Jon Clements 6/20/2012 #4

我会选择 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)]
-1赞 user2179861 5/3/2013 #5

你可以试试这个

def find(ch,string1):
    for i in range(len(string1)):
        if ch == string1[i]:
            pos.append(i)        
0赞 Arvind Kumar 8/23/2018 #6
x = "abcdabcdabcd"
print(x)
l = -1
while True:
    l = x.find("a", l+1)
    if l == -1:
        break
    print(l)

评论

5赞 L_J 8/23/2018
虽然此代码可以回答问题,但提供有关它如何以及为什么解决问题的信息可以提高其长期价值。
0赞 Nagama Inamdar 8/23/2018
@Arvind : 欢迎来到 Stackoverflow。你介意扩展你的答案让其他程序员理解吗?它究竟如何帮助解决问题。
1赞 Anton K 2/21/2020 #7

根据经验,NumPy 数组在处理 POD(普通旧数据)时通常优于其他解决方案。字符串是 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赞 Caspar V. 12/14/2023
对于 1MB 的输入字符串来说,这可能是正确的,但对于短字符串,第二种方法要快得多:我对一个 7 个字符的字符串测试了 100 万次迭代,find1() 需要 6199 毫秒,find2() 只需要 825 毫秒。
0赞 dashesy 4/8/2020 #8

这是 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
0赞 Jonathan 9/10/2020 #9

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

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

这遍历了 查找 ,始终从上一次迭代结束的地方开始。它使用内置的,这比逐个字符迭代要快得多。它不需要任何新的导入。haystackneedlestr.findhaystack

评论

0赞 wim 8/20/2021
这似乎与休·博思韦尔(Hugh Bothwell)2012年的回答相同
0赞 Jonathan 8/21/2021
@wim 哇,你是对的。不知道我是怎么错过的。
4赞 Babak Karchini 9/19/2020 #10
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]
4赞 Darkstar Dream 6/3/2021 #11

只需一行即可获得所有位置

word = 'Hello'
to_find = 'l'

# in one line
print([i for i, x in enumerate(word) if x == to_find])
0赞 Dr. C. 7/20/2021 #12

点缀@Lev和@Darkstar发布的五星单行文字:

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

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

1赞 Nick 11/17/2023 #13

我认为这是最简单的方法:

def find(ch, string1):
    return [i for i in range(len(string1)) if string1[i]==ch]

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