2010-01-31 17 views
20

Per gli elenchi, il metodo list.index(x) restituisce l'indice nell'elenco del primo elemento il cui valore è x. Ma se voglio dare un'occhiata agli elementi della lista, e non solo agli interi elementi, come faccio a utilizzare il metodo Pythoninc per questo?Ottieni il primo indice di elenco contenente la sottostringa?

Ad esempio, con

l = ['the cat ate the mouse', 
    'the tiger ate the chicken', 
    'the horse ate the straw'] 

questa funzione ritornerebbe 1 fornito con l'argomento tiger.

risposta

23

Un metodo non slicky:

def index_containing_substring(the_list, substring): 
    for i, s in enumerate(the_list): 
     if substring in s: 
       return i 
    return -1 
+0

Slicker del mio direi. + 1 ~ –

2
def find(l, s): 
    for i in range(len(l)): 
     if l[i].find(s)!=-1: 
      return i 
    return None # Or -1 
2

Questo è abbastanza liscia e abbastanza efficiente.

>>> def find(lst, predicate): 
...  return (i for i, j in enumerate(lst) if predicate(j)).next() 
... 
>>> l = ['the cat ate the mouse','the tiger ate the chicken','the horse ate the straw'] 
>>> find(l, lambda x: 'tiger' in x) 
1 

L'unico problema è che si alzerà StopIteration se l'oggetto non viene trovato (anche se questo è facilmente risolvibile).

+1

StopIteration può essere evitato: 'return next ((i per i, j in enumerate (lst) if predicate (j)), -1)' (Python 2.6+) – vsvasya

1
def first_substring(strings, substring): 
    return min(i for i, string in enumerate(strings) if substring in string) 

Nota: Ciò consentirà di aumentare ValueError nel caso in cui nessuna corrispondenza viene trovato, che è meglio a mio parere.

+0

Fancy ma non efficiente, in quanto verifica tutti gli elementi della lista indipendentemente dal fatto che il testo sia stato trovato in precedenza o meno. Inoltre, la funzione 'qualcosa'.find (s) di Python restituisce -1 quando non viene trovata alcuna corrispondenza, quindi chiamerei Pythonic. –

+0

Non funziona, almeno in Python 2.6. Non è possibile utilizzare sia un argomento iterabile che un argomento extra in 'min()'. @Etiene: questa è un'espressione di generatore, non una comprensione di lista, quindi non genererebbe tutto. –

+0

@Etienne - l'ottimizzazione prematura è la radice di tutti i mali ecc. @Max - sei corretto, corretto. – abyx

3

Variazione della soluzione abyx (ottimizzato per fermarsi quando viene trovato il match)

def first_substring(strings, substring): 
    return next(i for i, string in enumerate(strings) if substring in string) 

Se si sono pre 2.6 è necessario mettere la next() alla fine

def first_substring(strings, substring): 
    return (i for i, string in enumerate(strings) if substring in string).next() 
1
>>> li = ['my','array','with','words'] 
    >>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word == 'my' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0] 
    0 
    >>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word == 'words' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0] 
    3 
2

È possibile utilizzare il seguente one-liner:

index = [idx for idx, s in enumerate(l) if 'tiger' in s][0] 
Problemi correlati