2013-08-30 10 views
26

Gibt es eine gegebene Liste, gibt es eine Möglichkeit, den ersten Nicht-Nicht-Wert zu erhalten? Und wenn ja, was wäre der pythonische Weg dazu?Abrufen des ersten Nicht-Nicht-Werts aus der Liste

Zum Beispiel habe ich:

  • a = objA.addreses.country.code
  • b = objB.country.code
  • c = None
  • d = 'CA'

In diesem Fall, wenn ein Nichts ist, dann würde Ich mag bekommen b. Wenn a und b beide Keine sind, würde ich gerne d bekommen.

Momentan mache ich etwas in Richtung (((a or b) or c) or d), gibt es einen anderen Weg?

Antwort

62

Sie können next() verwenden:

>>> a = [None, None, None, 1, 2, 3, 4, 5] 
>>> next(item for item in a if item is not None) 
1 

Wenn die Liste nur Nones enthält, es StopIteration Ausnahme werfen. Wenn Sie einen Standardwert in diesem Fall haben wollen, dies tun:

>>> a = [None, None, None] 
>>> next((item for item in a if item is not None), 'All are Nones') 
All are Nones 
+3

Ich würde ein 'try:' 'außer StopIteration:' hinzufügen, um Listen zu behandeln, die nur keine Elemente enthalten. Aber das ist eine großartige Antwort. – Germano

+1

@Germano aktualisiert die Antwort, bitte überprüfen. Btw, Jons Antwort sollte akzeptiert werden - er schlug zuerst eine Lösung für Nicht-Listen vor. – alecxe

+0

eigentlich denke ich, Jon's Antwort ist nicht korrekt: es gibt nur 'True' oder' False' zurück, nicht das erste nicht 'None' Element der Liste. – Germano

4

Passen Sie eine der folgenden Optionen (man könnte Einzeiler es, wenn man wollte):

values = (a, b, c, d) 
not_None = (el for el in values if el is not None) 
value = next(not_None, None) 

Dies ist die erste nicht braucht None Wert oder gibt stattdessen None zurück.

+0

verstehe ich nicht. Wird das nicht nur "True" oder "False" gedruckt? – thefourtheye

+0

@thefourtheye ja - hatte ein Gehirn rülpsen ... danke für das Aufzeigen –

2

first_true ist ein itertools Rezept in der Python 3 docs gefunden:

def first_true(iterable, default=False, pred=None): 
    """Returns the first true value in the iterable. 

    If no true value is found, returns *default* 

    If *pred* is not None, returns the first item 
    for which pred(item) is true. 

    """ 
    # first_true([a,b,c], x) --> a or b or c or x 
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x 
    return next(filter(pred, iterable), default) 

Man kann wählen, letztere Rezept oder importieren more_itertools, eine Bibliothek, die Schiffe mit itertools Rezepte und mehr zu implementieren:

> pip install more_itertools 

Verwendung:

import more_itertools as mit 

a = [None, None, None, 1, 2, 3, 4, 5] 
mit.first_true(a, pred=lambda x: x is not None) 
# 1 

a = [None, None, None] 
mit.first_true(a, default="All are None", pred=lambda x: x is not None) 
# 'All are None' 

Warum das Prädikat verwenden?

"Erstes nicht None" Element ist nicht dasselbe wie "erstes True" Element, z. [None, None, 0] wobei 0 die erste nicht None ist, aber es ist nicht die erste True Artikel. Das Prädikat erlaubt first_true, verwendbar zu sein, um sicherzustellen, dass jedes zuerst gesehene, nicht-fehlende, falsche Element in dem iterierbaren Element (z. B. 0, False) anstelle des Standardwerts zurückgegeben wird.

a = [None, None, None, False] 
mit.first_true(a, default="All are None", pred=lambda x: x is not None) 
# 'False' 
Verwandte Themen