если / еще в понимании списка


905

Как я могу сделать следующее в Python?

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

По существу:

  1. заменить все Nones пустыми строками, а затем
  2. выполнять функцию.

Ответы:


1461

Вы можете сделать это полностью. Это просто вопрос заказа:

[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
Вот почему я предпочитаю помещать троичный оператор в скобки, так что становится понятнее, что это просто нормальное выражение, а не понимание.
Йохен Ритцель

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]. Извините за беспокойство. Спасибо за Ваш ответ.
Грижеш Чаухан

5
Документы Python упоминают троичный оператор . Обратите внимание, что требуется другое, или оно не работает.
naught101

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

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, порядок:

выражение для элемента в Iterable , если условие

и в последнем понимании списка X_str_changed, порядок:

выражение1, если условие еще выражение2 для элемента в итерируемом

Мне всегда трудно вспомнить, что expresseion1 должен быть до, если и expression2 должен быть после else . Моя голова хочет, чтобы оба были либо до, либо после.

Я предполагаю, что это разработано так, потому что это напоминает нормальный язык, например: «Я хочу оставаться внутри, если идет дождь, иначе я хочу выйти на улицу»

В простом английском языке два типа перечисленных выше пониманий списка могут быть сформулированы как:

Только с if:

извлекать для яблока в box_of_apples, если apple_is_ripe

и с if/else

mark_apple, если apple_is_ripe еще оставьте_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

Нет необходимости в троичной системе if / then / else. На мой взгляд, ваш вопрос требует этого ответа:

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
Второй дает ошибку, когда Тим ответил в своем комментарии, см. Также условные утверждения в документации по питону. Которые совершенно нечитаемы для меня. Сводка: this if condition else thatразрешено только или нормальное выражение. Нет value = this if condition(что может быть достигнуто с помощью value = this if condition else None)
Anderium

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]
Affichage de my_result_list [0, 5, 4, 7, 8, 9]

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


Что означает «Афиша де ...» ? Это французский?
Питер Мортенсен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.