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

时间:2012-06-20 14:55:40

标签: python string

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

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

该函数仅返回第一个索引。如果我更改返回打印,它将打印0 0 0.为什么这样,有没有办法获得0 1 2

13 个答案:

答案 0 :(得分:72)

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

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

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

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

答案 1 :(得分:16)

我会选择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)]

答案 2 :(得分:9)

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

答案 3 :(得分:6)

Lev's answer是我使用的,但是这里的内容基于您的原始代码:

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

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

答案 4 :(得分:2)

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]

答案 5 :(得分:1)

根据经验,在使用POD(普通旧数据)时,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

答案 6 :(得分:0)

你可以试试这个

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

答案 7 :(得分:0)

使用pandas,我们可以执行此操作并返回包含所有索引的dict,简单版本:

import pandas as pd

d = (pd.Series(l)
     .reset_index()
     .groupby(0)['index']
     .apply(list)
     .to_dict())

但我们也可以建立条件,例如只有两次或多次出现:

d = (pd.Series(l)
     .reset_index()
     .groupby(0)['index']
     .apply(lambda x: list(x) if len(list(x)) > 1 else None)
     .dropna()
     .to_dict())

答案 8 :(得分: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

答案 9 :(得分:0)

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

  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的速度要快得多。不需要任何新的导入。

答案 10 :(得分:0)

在一行中获取所有位置

word = 'Hello'
to_find = 'l'

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

答案 11 :(得分:0)

为了修饰@Lev 和@Darkstar 发布的五星级单线:

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

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

答案 12 :(得分:-1)

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