2010-03-03 10 views
6

Ich brauche eine Funktion, die in der Lage ist, über die Sammlung zu iterieren, indem sie eine übergebene Funktion mit dem Element der Sammlung als Parameter aufruft und den Parameter oder den Index zurückgibt, wenn sie von der angegebenen Funktion "True" erhalten.Python - funktional "finden"?

Es ist somethong wie folgt aus:

def find(f, seq, index_only=True, item_only=False): 
    """Return first item in sequence where f(item) == True.""" 
    index = 0 
    for item in seq: 
     if f(item): 
      if index_only: 
       return index 
      if item_only: 
       return item 
      return index, item 
     index+= 1 
    raise KeyError 

Also, ob ich frage mich, etwas gibt es wie in standart Python Toolset?

+2

Das Schnipsel des OP ist der direktere (wenn auch nur ein bisschen länger) Weg, die Anforderung auszudrücken; Je nach Situation kann dies der vorgeschriebene Weg sein. Aus den Antworten ergibt sich jedoch eine sehr nützliche Erkenntnis: "In Bezug auf Schleifen, im Zweifelsfall, konsultiere/betrachte itertools". – mjv

Antwort

2

Sie können itertools.dropwhile verwenden, um die Elemente zu überspringen, für die die angegebene Funktion False zurückgibt, und dann das erste Element des Rests (falls vorhanden). Wenn Sie den Index anstelle des Elements benötigen, integrieren Sie enumerate aus dem Abschnitt Rezepte von itertools docs.

Zur Wahrheitswerte umkehren durch die bereitgestellte Funktion zurückgegeben, verwenden Sie einen lambda (lambda x: not pred (x), wo pred die bereitgestellte Funktion ist) oder eine benannte Wrapper:

def negate(f): 
    def wrapped(x): 
     return not f(x) 
    return wrapped 

Beispiel: Dies wird

def odd(x): return x % 2 == 1 
itertools.dropwhile(negate(odd), [2,4,1]).next() 
# => 1 

Werfen Sie StopIteration, wenn kein passender Artikel gefunden wird; Wickeln Sie es in eine eigene Funktion, um stattdessen eine Ausnahme Ihrer Wahl zu werfen.

+0

:(Ich denke OP's Frage ist selbst die Antwort, dies kann etwas mehr für einfache Iteration sein. –

+0

Ich stimme mit Anurag überein, aber wenn 'itertools' verwendet wurden, denke ich' ifilter' wäre einfacher. Beispiel: 'itertools.ifilter (ungerade, [2,4,1]). next() ' – tgray

+0

Ich bin geneigt, dem" ifilter "zuzustimmen. Auch das OP-Snippet löst tatsächlich das Grundproblem, aber immer noch, ich frage mich, was da drin ist Standard lib, um zu vermeiden, Code für solche Sachen zu schreiben, scheint ziemlich vernünftig zu sein, ich würde sagen, dass der Kommentar von mjv zu dieser Frage die wichtige Lektion hier perfekt zusammenfasst. –

3

Ich glaube nicht, dass es eine solche Funktion mit einer solchen genauen Semantik gibt, und sowieso ist Ihre Funktion kurz, gut genug und Sie können es leicht für die spätere Verwendung verbessern, also verwenden Sie es.

weil einfach ist besser als komplex.

Verwandte Themen