2016-07-20 30 views
3

Ich schrieb einige strukturell gleichwertige realen Welt Code, wo ich das Ergebnis für firstAdjective wäre quick erwartet. Aber das Ergebnis zeigt, dass word außerhalb des Geltungsbereichs ist. Was ist eine saubere Lösung, die das überwinden wird, aber immer noch den "linguistischen" Stil dessen, was ich tun möchte, beibehalten möchte?Python: Erweiterung des Bereichs der Iterator-Variable in der any() -Funktion

>>> text = 'the quick brown fox jumps over the lazy dog' 
>>> adjectives = ['slow', 'quick', 'brown', 'lazy'] 
>>> if any(word in text for word in adjectives): 
...  firstAdjective = word 
...  
Traceback (most recent call last): 
    File "<interactive input>", line 2, in <module> 
NameError: name 'word' is not defined 
+1

Dies funktioniert nicht, da das ‚Wort‘ Objekt existiert nur während der Auswertung der Bedingung. Sobald festgestellt wurde, ob die Bedingung wahr oder falsch ist, existiert das Wort Objekt nicht mehr. – HolyDanna

+0

Was ist die erwartete Ausgabe, wenn 'text = 'a b'' und' adjectives = [' b ',' a '] '? –

+0

Wenn wir 'Adjektive = ['langsam', 'braun', 'faul', 'schnell']' als Liste der Adjektive verwenden würden, sollte es 'schnell' (zuerst im Text) oder 'braun' (Tannen in der Adjektivliste). (Das ist dasselbe wie Rawings Kommentar). Das Beispiel, das Sie geben, führt uns zur Verwirrung, da "schnell" das erste Adjektiv sowohl in der Liste von Adj als auch im Text ist .... – HolyDanna

Antwort

1

Sie next auf einem Generator Ausdruck verwenden können:

firstAdjective = next((word for word in adjectives if word in text), None) 

if firstAdjective: 
    ... 

Ein Standardwert von None zurückgegeben wird, wenn das Wort nicht gefunden wird (Kredit @Bakuriu)

Test :

>>> firstadjective = next((word for word in adjectives if word in text), None) 
>>> firstadjective 
'quick' 
+0

' next' kann auch einen Standardwert angeben: 'firstAdjektiv = next ((Wort für ...), None): if firstAdjektiv ist None: ...' – Bakuriu

+0

Sprite! Daran habe ich mich nicht erinnert. Danke –

+0

Jetzt ändere die Liste der Adjektive um 'Adjektive = ['langsam', 'braun', 'faul', 'schnell']'. Sie erhalten das erste Adjektiv in der Liste, anstatt das erste Adjektiv im Text (und mit der geänderten Adjektivliste erhalten Sie "braun" und nicht "schnell"). Siehe die Antwort von Mutational Meltdown, um ihren Platz im Text anstelle der Adjektivliste zu sehen. – HolyDanna

0

wäre so etwas wie

for word in filter(lambda x: x in adjectives, text.split()): 
    print word 

Arbeit?

+0

Ich denke David will nur das erste Adjektiv, wo deine Lösung alle drei zeigen würde. – HolyDanna

+0

Ein "Bruch" würde in diesem Fall tun. – dirkster

0

Ihr Beispiel funktioniert nicht, da die Variable word nur bei der Auswertung der Bedingung existiert. Sobald die Suche abgeschlossen ist, ob die Bedingung wahr oder falsch ist, wird die Variable nicht mehr verwendet und existiert nicht mehr.

erklärt es auch zuerst nicht hilft, da sie nicht die vorhandenen Variablen beeinflusst:

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['slow', 'quick', 'brown', 'lazy'] 
word = None 
if any(word in text for word in adjectives): 
    print(word) 

Keine

Deshalb haben Sie es anders machen, die unter Verwendung von next Funktion:

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['slow', 'quick', 'brown', 'lazy'] 
word = next((word for word in adjectives if word in text), None) 
if word: 
    print(word) 

schnell

Hinweis ist vielleicht word eine irreführende Variablennamen hier, weil es nicht unbedingt haben ein ganzes Wort übereinstimmen. dh

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['slo', 'uick', 'rown', 'azy'] 
word = next((word for word in adjectives if word in text), None) 
if word: 
    print(word) 

urz

so könnte es am besten sein, den Text in Worte zu spalten zuerst:

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['slow', 'quick', 'brown', 'lazy'] 
word_list = text.split() 
word = next((word for word in adjectives if word in word_list), None) 
if word: 
    print(word) 

aber beachten Sie, dass, wenn wir die Adjektive ändern bestellen:

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['brown', 'quick', 'slow', 'lazy'] 
word_list = text.split() 
word = next((word for word in adjectives if word in word_list), None) 
if word: 
    print(word) 

erhalten wir:

braun

, die nicht das erste Adjektiv im Text ist.

Daher müssen wir in der Reihenfolge der Wörter im Text überprüfen, nicht die Reihenfolge der Adjektive in der Liste.

text = 'the quick brown fox jumps over the lazy dog' 
adjectives = ['brown', 'quick', 'slow', 'lazy'] 
word_list = text.split() # NOTE: this "optimization" is no longer necessary now 
word = next((word for word in word_list if word in adjectives), None) 
if word: 
    print(word) 

credit to HolyDanna for spotting this

+0

Sie sehen ihren Platz in der Liste der Adjektive und nicht im Text. Sie sollten Wort für Wort in text.split() es Wort in Adjektiven gehen, wenn Sie ihren Platz im Text sehen wollen. – HolyDanna

+0

@HolyDanna guten Fang - danke! –

+0

In Python 2.7 zumindest scheint es, dass text.split() tatsächlich notwendig ist. Sehen Sie meine bearbeitete (und herabgestufte) Antwort unten. Ich habe es als eine andere Antwort eingegeben, weil ich nicht weiß, wie man Code in Kommentare wie diesen einfügt. –

-1
>>> text = 'the quick brown fox jumps over the lazy dog' 
>>> 
>>> # 1. Case with no match among the adjectives: Result None as expected 
>>> adjectives = ['slow', 'crippled'] 
>>> firstAdjective = next((word for word in adjectives if word in text), None) 
>>> firstAdjective 
>>> 
>>> # 2. Case with a match to 1st available in adjectives but actually 2nd in the text 
>>> adjectives = ['slow', 'brown', 'quick', 'lazy'] 
>>> firstAdjective = next((word for word in adjectives if word in text), None) 
>>> firstAdjective 
'brown' 
>>> # 3. Case with a match to 1st available in the text, which is what is wanted 
>>> firstAdjective = next((word for word in text.split() if word in adjectives), None) 
>>> firstAdjective 
'quick' 
>>> # 4. Case where .split() is omitted. NOTE: This does not work. 
>>> # In python 2.7 at least, .split() is required 
>>> firstAdjective = next((word for word in text if word in adjectives), None) 
>>> firstAdjective 
>>>