2016-03-30 17 views
2

Ist es möglich, das Zufallsmodul zu verwenden, um Strings aus einer Liste zu extrahieren, aber nur, wenn der String eine Länge größer als x hat?Zufallswerte aus der Liste extrahieren, die Kriterien erfüllen? Python

Zum Beispiel:

list_of_strings = ['Hello', 'Hello1' 'Hello2'] 

Wenn Sie x = 5 und Rufaufbau random.choice() würde der Code zwischen nur list_of_strings[1] und list_of_strings[2] 'Wahl' werden.

Ich weiß, Sie könnten eine zweite Liste machen, die nur Werte von len > x enthält, aber ich würde gerne wissen, ob es ohne diesen Schritt möglich ist.

+0

Listenverständnis? –

+0

IOW, es ist möglich, eine Schleife zu verwenden, aber wahrscheinlich besser, nur Verständnis zu verwenden. –

+0

nicht so sicher, aber Comprehensions erstellen auch eine andere Liste. – krato

Antwort

4
random.choice([s for s in list_of_strings if len(s) > x]) 

Oder Sie so etwas tun könnte:

while True: 
    choice = random.choice(list_of_strings) 
    if len(choice) > x: 
     return choice 

Sie sollten zunächst prüfen, ob Strings in der Liste enthalten sind, die als x länger sonst wird dieser Code nie enden.

Eine andere mögliche Lösung ist die Verwendung von Reservoir-Probenahmen, sie hat den zusätzlichen Vorteil einer begrenzten Laufzeit.

+1

* "Ich weiß, Sie könnten eine zweite Liste erstellen, die nur Werte enthält von len> x aber ich würde gerne wissen, ob es ohne diesen Schritt möglich ist. "* – Christian

+0

Es wird auch langsam, wenn es nicht viele Elemente gibt, die die Bedingung erfüllen. Siehe meine Antwort für weitere Details. – arekolek

0

Sie können dies tun:

random.choice([i for i in list_of_strings if len(i) > x]) 
+0

* "Ich weiß, Sie könnten eine zweite Liste erstellen, die nur Werte von len> x enthält, aber ich würde gerne wissen, ob es ohne diesen Schritt möglich ist." * – Christian

1

andere Lösung, die keine zusätzliche Liste nicht erstellen:

from itertools import islice 
from random import randrange 

def choose_if(f, s): 
    return next(islice(filter(f, s), randrange(sum(map(f, s))), None)) 

choose_if(lambda x: len(x) > 5, list_of_strings) 

Stellt sich heraus, es ist fast zwei Mal langsamer als Christian-Lösung ist. Das liegt daran, dass es zweimal über s iteriert und f auf jedes Element anwendet. Es ist teuer genug, um den Gewinn aufzuwiegen, wenn keine zweite Liste erstellt wird.

Franciscos Lösung dagegen kann 10 bis 100 mal schneller sein, weil sie f nur so oft anwendet, wie es nicht gelungen ist, ein geeignetes Element auszuwählen. Hier ist eine vollständige Version dieser Funktion:

from random import choice 

def choose_if(f, s): 
    if any(filter(f, s)): 
    while True: 
     x = choice(s) 
     if f(x): return x 

Beachten Sie beginnt es noch schlimmer werden, wenn nur wenige (weniger als 1%) Elemente, die die Bedingung erfüllen. Wenn nur ein Element in 5000 gut war, war es 5 mal langsamer als ein Listenverständnis.

Verwandte Themen