web-dev-qa-db-fra.com

python - recherche le caractère dans la chaîne - puis-je obtenir tous les index?

J'ai un code simple:

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

La fonction ne renvoie que le premier index. Si je change de retour en impression, il sera imprimé 0 0 0. Pourquoi et pourquoi y a-t-il moyen d'obtenir 0 1 2

36
William Xing

En effet, str.index(ch) renverra l'index où ch apparaît la première fois. Essayer:

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

Cela renverra une liste de tous les index dont vous avez besoin.

P.S. La réponse de Hugh montre une fonction génératrice (cela fait une différence si la liste des index peut devenir volumineuse). Cette fonction peut également être ajustée en remplaçant [] par ().

70
Lev Levitsky

J'irais avec Lev, mais il vaut la peine de préciser que, si vous vous retrouvez avec des recherches plus complexes, l'utilisation de re.finditer peut être utile de garder à l'esprit (mais cela cause souvent plus de problèmes que de bien, mais il est parfois utile de savoir).

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)]
16
Jon Clements
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

résulte en

0
1
2
9
Hugh Bothwell

La réponse de Lev est celle que j'utiliserais, cependant voici quelque chose basé sur votre code d'origine:

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

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

Tu pourrais essayer ça

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

En utilisant des pandas, nous pouvons le faire et renvoyer un dict avec tous les indices, version simple:

import pandas as pd

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

Mais nous pouvons également créer des conditions, par exemple seulement si deux occurrences ou plus:

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