2010-01-31 4 views
20

Pour les listes, la méthode list.index(x) renvoie l'index dans la liste du premier élément dont la valeur est x. Mais si je veux regarder à l'intérieur des éléments de la liste, et pas seulement à l'ensemble des éléments, comment puis-je faire la plus grande méthode Pythoninc pour cela?Obtenir le premier index de liste contenant une sous-chaîne?

Par exemple, avec

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

cette fonction retournerait 1 fournie avec l'argument tiger.

Répondre

23

Méthode 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 que le mien, je dirais. + 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

Ceci est assez lisse et assez efficace.

>>> 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 

Le seul problème est qu'il soulèvera StopIteration si l'élément est introuvable (bien que cela soit facile d'y remédier).

+1

StopIteration peut être évité: 'retour suivant ((i pour i, j dans enumerate (lst) si prédicat (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) 

Note: Cela soulèvera ValueError si aucune correspondance est trouvée, ce qui est mieux à mon avis.

+0

Fantaisie mais pas efficace, car il teste tous les éléments de la liste, que le texte ait été trouvé précédemment ou non. En outre, la fonction 'something'.find (s)' de Python retourne -1 lorsqu'aucune correspondance n'est trouvée, donc j'appellerais cela Pythonic. –

+0

Ne fonctionne pas, au moins en Python 2.6. Vous ne pouvez pas utiliser à la fois un argument itérable et un argument supplémentaire dans 'min()'. @Etiene: c'est une expression génératrice, pas une compréhension de liste, donc ça ne génèrerait pas tout. –

+0

@Etienne - l'optimisation prématurée est la racine de tout le mal, etc. @Max - vous avez raison, corrigé. – abyx

3

Variation de la solution abyx (optimisé pour arrêter quand le match se trouve)

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

Si vous êtes pré 2.6, vous aurez besoin de mettre le next() à la fin

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

Vous pouvez utiliser le doublure suivante:

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