2012-06-20 15 views
32

Tengo algunas código simple:python - encontrar char en cadena - ¿puedo obtener todos los índices?

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

La función sólo devuelve el primer índice. Si cambio volver a imprimir, se imprimirá 0 0 0. ¿Por qué es esto y hay alguna forma de obtener 0 1 2?

+6

Solo así se dice, no use str como nombre de variable, ya que es una palabra clave existente en Python. –

+1

@ sr2222: 'str' no es una palabra clave, es solo un nombre incorporado (las palabras clave son imposibles de usar como nombres de variable) – geoffspear

+1

@Wooble Lo suficientemente justo. No cambia el hecho de que usarlo como nombre de variable es una mala práctica. :) –

Respuesta

65

Esto es porque str.index(ch) devolverá el índice donde ch se produce la primera vez. Proveedores:

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

Esto devolverá una lista de todos los índices que necesita.

P.S. La respuesta de Hugh muestra una función de generador (hace una diferencia si la lista de índices puede agrandarse). Esta función también se puede ajustar cambiando [] a ().

+0

Usando 'enumerate', buena solución! – lmichelbacher

+0

ch debe ser un solo carácter? Lo intenté usando 'ch = '& #'' y 's = Н а р о д' y eso no funcionó. –

+0

@ChrisNielsen, de hecho, esto no funcionará para subcadenas más largas porque 'enumerate' itera sobre los caracteres en' s' y por lo tanto 'ltr == ch' solo puede ser' True' si 'ch' es un solo carácter. –

7
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 

resultados en

0 
1 
2 
5

Lev's answer es el que yo uso, sin embargo, aquí hay algo basado en el código original:

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

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

Me gustaría ir con Lev, pero vale la pena señalando que si termina con búsquedas más complejas, puede ser útil tener en cuenta el uso de re.finditer (pero a menudo causa más problemas que valía, pero a veces es útil saberlo)

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

Usted podría intentar esto

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

muchas alternativas el uso de expresiones regulares

import re 

iter = re.finditer(r'o', searchString) 

indexes = [x.start() for x in iter] 

índices es la lista de los índices de cadenas para los partidos

0

Uso de pandas que podemos hacer esto y devuelve un dict con todos los índices, versión simple:

import pandas as pd 

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

Pero también podemos construir en condiciones, p. solo si hay dos o más ocurrencias:

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