查找字符串中某个字符的所有位置

Ama*_*us 3 python for-loop

我正在尝试使用非常基本的技能集在 python 字符串中查找字符的所有索引号。例如,如果我有字符串“Apples are fully awesome”,并且我想找到字符串中 'a' 的位置。我的理想输出是:

0
7
14
19
Run Code Online (Sandbox Code Playgroud)

这些是字符串中出现“a”的所有位置(我认为)

这是我到目前为止的代码:

sentence = input("Input a string: ")
for ch in sentence:
    x = sentence.find('o')


print(x)
Run Code Online (Sandbox Code Playgroud)

在这里,我正在寻找 'o' 而不是 a。我的想法是,对于字符串中的每个字符,find 函数都会返回 'o' 的位置。因为我不知道输入字符串需要多长时间,所以我使用了 for 循环。我能够找到并打印出“o”的第一个实例,但不是全部。我该怎么办?提前致谢!

Oli*_*çon 6

使用enumerate是标准的方法。不过,您可以利用 速度来str.find进行时间紧迫的操作。

代码

def find_all(s, c):
    idx = s.find(c)
    while idx != -1:
        yield idx
        idx = s.find(c, idx + 1)

print(*find_all('Apples are totally awesome', 'o')) # 12 23
Run Code Online (Sandbox Code Playgroud)

为了优雅和考虑非常大的字符串,我使上面的返回一个生成器。list如果需要,当然可以将它转换为 a 。

基准

这是针对使用enumerate和列表理解的解决方案的基准。两种解决方案都具有线性时间复杂度,但str.find速度明显更快。

import timeit

def find_all_enumerate(s, c):
    return [i for i, x in enumerate(s) if c == 'a']

print(
    'find_all:',
    timeit.timeit("list(find_all('Apples are totally awesome', 'o'))",
                  setup="from __main__ import find_all")
)

print(
    'find_all_enumerate:',
    timeit.timeit("find_all_enumerate('Apples are totally awesome', 'o')",
                  setup="from __main__ import find_all_enumerate")
)
Run Code Online (Sandbox Code Playgroud)

输出

find_all: 1.1554179692960915
find_all_enumerate: 1.9171753468076869
Run Code Online (Sandbox Code Playgroud)


vas*_*ede 1

这是enumerate的好地方,它允许我们在循环时获得index and item,所以如果我们匹配item我们可以得到相应的index,它也有助于.lower()避免匹配案例的问题

s = 'Apples are totally awesome'

l = [idx for idx, item in enumerate(s.lower()) if 'o' in item]
Run Code Online (Sandbox Code Playgroud)

扩展循环:

l = []
for idx, item in enumerate(s.lower()):
    if 'o' in item:
        l.append(idx)
Run Code Online (Sandbox Code Playgroud)
/python/stack$ python3.7 sum.py 
[12, 23]
Run Code Online (Sandbox Code Playgroud)