Як встановити два цикли для циклів у розумінні списку python


101

У мене є два списки, як показано нижче

tags = [u'man', u'you', u'are', u'awesome']
entries = [[u'man', u'thats'],[ u'right',u'awesome']]

Я хочу витягти записи, entriesколи вони знаходяться в tags:

result = []

for tag in tags:
    for entry in entries:
        if tag in entry:
            result.extend(entry)

Як я можу написати два цикли як розуміння списку в один рядок?


3
Використовуйте, itertools.chainякщо хочете сплощений список:list(chain.from_iterable(entry for tag in tags for entry in entries if tag in entry))
Ашвіні Чаудхарі

Відповіді:


135

Це має зробити це:

[entry for tag in tags for entry in entries if tag in entry]

157

Найкращий спосіб запам'ятати це те, що порядок циклу for всередині розуміння списку базується на порядку, в якому вони з'являються в традиційному підході циклу. Спочатку виходить сама зовнішня петля, а потім внутрішні петлі.

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

[entry for tag in tags for entry in entries if tag in entry]

Загалом, if-elseтвердження поставляється перед першим циклом for, і якщо у вас є лише ifвираз, він прийде в кінці. Наприклад, якщо ви хочете додати порожній список, якщо tagйого немає в записі, ви зробите це так:

[entry if tag in entry else [] for tag in tags for entry in entries]

6

Відповідний LC буде

[entry for tag in tags for entry in entries if tag in entry]

Порядок циклів у LC схожий на порядок у вкладених циклах, якщо оператори if йдуть до кінця, а умовні вирази йдуть на початку, щось на зразок

[a if a else b for a in sequence]

Дивіться демонстрацію -

>>> tags = [u'man', u'you', u'are', u'awesome']
>>> entries = [[u'man', u'thats'],[ u'right',u'awesome']]
>>> [entry for tag in tags for entry in entries if tag in entry]
[[u'man', u'thats'], [u'right', u'awesome']]
>>> result = []
    for tag in tags:
        for entry in entries:
            if tag in entry:
                result.append(entry)


>>> result
[[u'man', u'thats'], [u'right', u'awesome']]

РЕДАГУВАТИ - Оскільки вам потрібно згладити результат, ви можете скористатися схожим розумінням списку, а потім згладити результати.

>>> result = [entry for tag in tags for entry in entries if tag in entry]
>>> from itertools import chain
>>> list(chain.from_iterable(result))
[u'man', u'thats', u'right', u'awesome']

Додавши це разом, ви могли б просто зробити

>>> list(chain.from_iterable(entry for tag in tags for entry in entries if tag in entry))
[u'man', u'thats', u'right', u'awesome']

Тут ви використовуєте генераторський вираз замість розуміння списку. (Також ідеально відповідає обмеженню в 79 символів (без listдзвінка))


2
tags = [u'man', u'you', u'are', u'awesome']
entries = [[u'man', u'thats'],[ u'right',u'awesome']]

result = []
[result.extend(entry) for tag in tags for entry in entries if tag in entry]

print(result)

Вихід:

['man', 'thats', 'right', 'awesome']

0

З розумінням, ітерація вкладених списків повинна слідувати в тому ж порядку, що і еквівалент, вбудований для циклів.

Щоб зрозуміти, ми візьмемо простий приклад з НЛП. Ви хочете створити список усіх слів із списку речень, де кожне речення є списком слів.

>>> list_of_sentences = [['The','cat','chases', 'the', 'mouse','.'],['The','dog','barks','.']]
>>> all_words = [word for sentence in list_of_sentences for word in sentence]
>>> all_words
['The', 'cat', 'chases', 'the', 'mouse', '.', 'The', 'dog', 'barks', '.']

Щоб видалити повторювані слова, ви можете використовувати набір {} замість списку []

>>> all_unique_words = list({word for sentence in list_of_sentences for word in sentence}]
>>> all_unique_words
['.', 'dog', 'the', 'chase', 'barks', 'mouse', 'The', 'cat']

або подати заявку list(set(all_words))

>>> all_unique_words = list(set(all_words))
['.', 'dog', 'the', 'chases', 'barks', 'mouse', 'The', 'cat']

0
return=[entry for tag in tags for entry in entries if tag in entry for entry in entry]

6
Привіт та ласкаво просимо до Stack Overflow! Будь ласка, опублікуйте пояснення, а не лише код.
Евелін

1
Привіт! Хоча цей код може вирішити питання, включаючи пояснення того, як і чому це вирішує проблему, справді допомогло б поліпшити якість вашої публікації, і, можливо, призведе до збільшення кількості голосів. Пам’ятайте, що ви відповідаєте на запитання читачам у майбутньому, а не лише тому, хто задає зараз. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Брайан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.