jeśli / else w zrozumieniu listy

Odpowiedzi:

1456

Możesz to zrobić całkowicie. To tylko kwestia zamówienia:

[unicode(x.strip()) if x is not None else '' for x in row]

Ogólnie,

[f(x) if condition else g(x) for x in sequence]

I tylko w przypadku list ze zrozumieniem z ifwarunkami

[f(x) for x in sequence if condition]

Zauważ, że tak naprawdę używa innej konstrukcji języka, wyrażenia warunkowego , które samo w sobie nie jest częścią składni rozumienia , podczas gdy ifpo for…injest częścią wyrażeń listowych i służy do filtrowania elementów ze źródła iterowalnego.


Wyrażeń warunkowych można używać we wszystkich sytuacjach, w których chcesz wybierać między dwiema wartościami wyrażeń na podstawie pewnych warunków. Robi to tak samo, jak operator trójskładnikowy, ?:który istnieje w innych językach . Na przykład:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
szturchać
źródło
141
Zauważ, że tutaj if / else jest teraz składnią „potrójnego operatora”, a nie składnią ze zrozumieniem.
Adam Vandenberg,
8
Dlatego wolę umieszczać operator trójskładnikowy w nawiasach, dzięki czemu jest bardziej zrozumiałe, że jest to zwykłe wyrażenie, a nie zrozumienie.
Jochen Ritzel
17
Zatem sztuczka polega na tym, że „w kompresji listy piszę, jeśli wcześniej, to muszę dodać jeszcze część”. bo jeśli mój, l = [ 2, 3, 4, 5]to [x if x % 2 == 0 for x in l]daj mi błąd, ale [x if x % 2 == 0 else 200 for x in l]działa. Tak, wiem, żeby to przefiltrować, powinienem napisać [ x for x in l if x % 2 == 0]. Przepraszam, że przeszkadzam. Dzięki za odpowiedź.
Grijesh Chauhan
5
Dokumenty Pythona wspominają o potrójnym operatorze . Zauważ, że wymaga innego lub nie działa.
naught101
4
@ Wyrażenia listyDrewdin nie obsługują łamania podczas iteracji. Będziesz wtedy musiał użyć normalnej pętli.
poke
44

Jednokierunkowa:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

Chociaż wtedy masz:

row = map(change, row)

Lub możesz użyć liniowego lambda.

Adam Vandenberg
źródło
13
Jest to również dobra (może tylko) technika, którą należy zastosować, gdy trzeba obsłużyć możliwe wyjątki od ifwyrażenia lub kodu w jego elsebloku instrukcji lub s. Przyjęta odpowiedź jest lepsza w prostych przypadkach.
martineau,
37

Oto kolejny przykładowy przykład:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

Wykorzystuje fakt, że if iocenia Falsedla 0i Truedla wszystkich innych wartości generowanych przez funkcję range(). W związku z tym zrozumienie listy ocenia się następująco:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
Bengt
źródło
37

Konkretny problem został już rozwiązany w poprzednich odpowiedziach, więc zajmę się ogólną ideą używania warunkowych w ramach list.

Oto przykład, który pokazuje, w jaki sposób warunek można zapisać wewnątrz listy:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

Zauważ, że w pierwszym zestawieniu listy X_non_strkolejność jest następująca:

Wyrażenie dla pozycji w iterable jeśli warunek

aw ostatnim zestawieniu listy X_str_changedkolejność jest następująca:

wyrażenie1, jeśli warunek inny wyrażenie2 dla elementu w iterowalnym

Zawsze trudno jest pamiętać, że expresseion1 musi być wcześniej czy i wyrażenie2 musi być po indziej . Moja głowa chce być zarówno przed, jak i po.

Myślę, że jest zaprojektowany tak, ponieważ przypomina normalny język, na przykład: „Chcę pozostać wewnątrz jeśli pada deszcz, jeszcze chcę wyjść na zewnątrz”

W prostym języku angielskim dwa wyżej wymienione typy list można określić jako:

Tylko z if:

extract_apple for apple in box_of_apples if apple_is_ripe

i z if/else

mark_apple, jeśli apple_is_ripe else pozostaw_nieznaczony dla apple w box_of_apples

Tim Skov Jacobsen
źródło
7

Inne rozwiązania są świetne dla pojedynczego if/ elsekonstruktu. Jednak wyrażenia trójkowe w ramach list są prawdopodobnie trudne do odczytania.

Korzystanie z funkcji poprawia czytelność, ale takie rozwiązanie jest trudne do rozszerzenia lub dostosowania w przepływie pracy, w którym mapowanie stanowi dane wejściowe. Słownik może złagodzić te obawy:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
jpp
źródło
1

Ma to związek z tym, w jaki sposób wykonywane jest rozumienie listy.

Pamiętaj, że:

[ expression for item in list if conditional ]

Jest równa:

for item in list:
    if conditional:
        expression

Gdzie expressionjest w nieco innym formacie (pomyśl o zmianie tematu i kolejności czasowników w zdaniu).

Dlatego twój kod [x+1 for x in l if x >= 45]robi to:

for x in l:
    if x >= 45:
        x+1

Jednak ten kod [x+1 if x >= 45 else x+5 for x in l]robi to (po zmianie expression):

for x in l:
    if x>=45: x+1
    else: x+5
arboc7
źródło
0

Nie ma potrzeby tworzenia trójki, jeśli / to / else. Moim zdaniem twoje pytanie wymaga tej odpowiedzi:

row = [unicode((x or '').strip()) for x in row]
mariotomo
źródło
0

Zrób listę z elementów w iteracji

Wydaje się, że najlepiej najpierw uogólnić wszystkie możliwe formularze, a nie udzielić konkretnych odpowiedzi na pytania. W przeciwnym razie czytelnik nie będzie wiedział, w jaki sposób ustalono odpowiedź. Oto kilka uogólnionych formularzy, które wymyśliłem, zanim dostałem bólu głowy, próbując zdecydować, czy można użyć ostatniej klauzuli „else” w ostatniej formie.

[expression1(item)                                        for item in iterable]

[expression1(item) if conditional1                        for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable if conditional2]

Wartość itemnie musi być używana w żadnej z klauzul warunkowych. A conditional3może służyć jako przełącznik do dodawania lub nie dodawania wartości do listy wyników.

Na przykład, aby utworzyć nową listę, która eliminuje puste ciągi lub ciągi spacji z oryginalnej listy ciągów:

newlist = [s for s in firstlist if s.strip()]
Hewey Dewey
źródło
1
Drugi podaje błąd, gdy Tim odpowiedział w swoim komentarzu, zobacz także instrukcje warunkowe w dokumentacji Pythona. Które są dla mnie dość nieczytelne. Podsumowanie: this if condition else thatdozwolone jest tylko wyrażenie normalne. Nie value = this if condition(co można osiągnąć za pomocą value = this if condition else None)
Anderium
0

Możesz połączyć logikę warunkową ze zrozumieniem:

 ps = PorterStemmer()
 stop_words_english = stopwords.words('english')
 best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]
 bestwords = set([w for w, s in best])


 def best_word_feats(words):
   return dict([(word, True) for word in words if word in bestwords])

 # with stemmer
 def best_word_feats_stem(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords])

 # with stemmer and not stopwords
 def best_word_feats_stem_stop(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords and word not in stop_words_english])
Max Kleiner
źródło
-2
# coding=utf-8

def my_function_get_list():
    my_list = [0, 1, 2, 3, 4, 5]

    # You may use map() to convert each item in the list to a string, 
    # and then join them to print my_list

    print("Affichage de my_list [{0}]".format(', '.join(map(str, my_list))))

    return my_list


my_result_list = [
   (
       number_in_my_list + 4,  # Condition is False : append number_in_my_list + 4 in my_result_list
       number_in_my_list * 2  # Condition is True : append number_in_my_list * 2 in my_result_list
   )

   [number_in_my_list % 2 == 0]  # [Condition] If the number in my list is even

   for number_in_my_list in my_function_get_list()  # For each number in my list
]

print("Affichage de my_result_list [{0}]".format(', '.join(map(str, my_result_list))))

(venv) $ python list_comp.py
Affichage de my_list [0, 1, 2, 3, 4, 5]
Affichage de my_result_list [0, 5, 4, 7, 8, 9]

Więc dla ciebie: row = [('', unicode(x.strip()))[x is not None] for x in row]

Trop Freshloïc
źródło
Co oznacza „Affichage de ...” ? Czy to francuski
Peter Mortensen