якщо / інше в списку розуміння


902

Як я можу зробити наступне в Python?

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

По суті:

  1. замініть усі нони порожніми рядками, а потім
  2. виконують функцію.

Відповіді:


1456

Ви цілком можете це зробити. Це лише питання замовлення:

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

В загальному,

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

А для розуміння списку ifлише з умовами,

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

Зауважимо, що для цього фактично використовується інша мовна конструкція, умовне вираження , яке саме по собі не є частиною синтаксису розуміння , тоді як " ifпісля" for…inє частиною розуміння списку і використовується для фільтрування елементів із вихідного ітерабельного джерела.


Умовні вирази можна використовувати у будь-яких ситуаціях, коли потрібно вибирати між двома значеннями виразів, виходячи з якоїсь умови. Це робить те саме, що і потрійний оператор, ?:який існує іншими мовами . Наприклад:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')

141
Зауважте, що синтаксис if / else тут є синтаксисом "потрійного оператора", а не списком синтаксису розуміння.
Адам Ванденберг

8
Ось чому я вважаю за краще ставити потрійний оператор в дужки, це стає зрозумілішим, що це просто нормальний вираз, а не розуміння.
Jochen Ritzel

17
Отже, хитрість полягає в тому, що "У списку стиснення я пишу, якщо раніше, тоді мені теж додати ще частину". тому що якщо моя l = [ 2, 3, 4, 5]тоді [x if x % 2 == 0 for x in l]дай мені помилку, тоді як [x if x % 2 == 0 else 200 for x in l]працює. Так, я знаю, щоб це відфільтрувати, я повинен написати [ x for x in l if x % 2 == 0]. Вибачте за турботу. Дякую за вашу відповідь.
Grijesh Chauhan

5
Документи пітона згадують про потрійний оператор . Зверніть увагу, що це вимагає іншого, або він не працює.
naught101

4
Поняття списку @Drewdin не підтримують злам під час його ітерації. Тоді вам доведеться використовувати звичайний цикл.
ткнути

44

Односторонній:

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

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

Хоча тоді у вас є:

row = map(change, row)

Або ви можете використовувати лямбда-лайнд.


13
Це також хороший (можливо, єдиний) прийом, який потрібно використовувати, коли вам доведеться обробляти можливі винятки з ifвиразу або коду в його elseблоці операторів s. Прийнята відповідь краще для простих випадків.
мартіно

37

Ось ще один наочний приклад:

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

Він використовує той факт, який if iоцінює Falseдля 0та Trueдля всіх інших значень, породжених функцією range(). Тому розуміння списку оцінюється наступним чином:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']

37

Конкретна проблема вже вирішена в попередніх відповідях, тому я торкнуся загальної ідеї використання умовних умов у розумінні списку.

Ось приклад, який показує, як умовні умови можна записати всередині списку:

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

Зауважте, що в першому списку розуміння для X_non_strпорядку:

вираз для елемента в ітерабельному, якщо умова

і в останньому розумінні списку для X_str_changedпорядку:

вираження1 якщо умова ще вираженія2 для пункту в ітерації

Я завжди знаходжу це важко згадати , що expresseion1 повинен бути перед , якщо і вираженія2 повинен бути після ще . Моя голова хоче, щоб обидва були або до, або після.

Я думаю, він створений так, тому що він нагадує звичайну мову, наприклад, "я хочу залишитися всередині, якщо дощить, інакше я хочу вийти назовні"

На звичайній англійській мові два типи розуміння списку, зазначені вище, можуть бути зазначені як:

Тільки з if:

extra_apple для яблука в box_of_apples, якщо apple_is_ripe

і с if/else

mark_apple якщо apple_is_ripe else left_it_unmarked для яблука в box_of_apples


7

Інші рішення чудово підходять для одиночного if/ elseконструкції. Однак потрійні твердження в межах списків, можливо, важко читати.

Використання функції сприяє читабельності, але таке рішення важко розширити або адаптувати в робочому процесі, де відображення є вхідним. Словник може полегшити ці проблеми:

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', '']

1

Це стосується того, як здійснюється розуміння списку.

Майте на увазі наступне:

[ expression for item in list if conditional ]

Еквівалентний:

for item in list:
    if conditional:
        expression

Де expressionу дещо іншому форматі (подумайте про переключення теми та порядку дієслів у реченні).

Тому ваш код [x+1 for x in l if x >= 45]робить це:

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

Однак цей код [x+1 if x >= 45 else x+5 for x in l]робить це (після перестановки expression):

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

0

Немає ніякої потреби в тернарі, якщо / тоді / ще. На мою думку, ваше запитання вимагає такої відповіді:

row = [unicode((x or '').strip()) for x in row]

0

Складіть список із предметів, які можна переглядати

Здається, спочатку узагальнити всі можливі форми, а не давати конкретні відповіді на запитання. Інакше читач не дізнається, як була визначена відповідь. Ось декілька узагальнених форм, які я придумав, перш ніж боліти голову, намагаючись вирішити, чи можна використовувати остаточну пропозицію в останній формі.

[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]

Значення itemне потрібно використовувати в жодному з умовних пунктів. A conditional3може використовуватися як перемикач для додавання або не додавання значення до списку вихідних даних.

Наприклад, створити новий список, який виключає порожні рядки або рядки пробілу з початкового списку рядків:

newlist = [s for s in firstlist if s.strip()]

1
Другий з них дає помилку, коли Тім відповів у своєму коментарі, також дивіться умовні твердження в документах python. Які для мене цілком нечитабельні. Підсумок: дозволено лише this if condition else thatабо нормальний вираз. Ніvalue = this if condition (чого можна досягти value = this if condition else None)
Андерюм

0

Ви можете поєднати умовну логіку в розумінні:

 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])

-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]
Доступність my_result_list [0, 5, 4, 7, 8, 9]

Отже, для вас: row = [('', unicode(x.strip()))[x is not None] for x in row]


Що означає "Affichage de ..." ? Це французька мова?
Пітер Мортенсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.