私は以下の2つのリストを持っています
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)
2つのループを1行のリスト内包表記として書くにはどうすればよいですか?
これはそれを行う必要があります:
[entry for tag in tags for entry in entries if tag in entry]
これを覚える最良の方法は、リスト内包内の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]
適切な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']]
EDIT-結果をフラット化する必要があるため、同様のリスト内包表記を使用して、結果をフラット化できます。
>>> 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
呼び出しなし))
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']