次のコードを「pythonic」に切り取ったものを作成するにはどうすればよいですか。
tag_list = []
for d in docs:
tags = d["tags"]
for tag in tags:
if tag not in tag_list:
tag_list.append(tag)
次のコードを「pythonic」に切り取ったものを作成するにはどうすればよいですか。
tag_list = []
for d in docs:
tags = d["tags"]
for tag in tags:
if tag not in tag_list:
tag_list.append(tag)
3.x(そしておそらく2.7、私は覚えていません)では、集合の内包的理解を行うことができます:
tag_list = {tag for doc in docs for tag in doc["tags"]}
2.xでは、ジェネレータ式からセットを作成できます。
tag_list = set(tag for doc in docs for tag in doc["tags"])
その後、本当にリストとして必要な場合は、実行してくださいlist(tag_list)
。
taglist = set()
for d in docs:
taglist |= set(d["tags"])
taglist = list(taglist)
また
from itertools import chain
taglist = list(set(chain(*(d["tags"] for d in docs))))
または(thxから@ lazy1):
from itertools import chain
taglist = list(set(chain.from_iterable(d["tags"] for d in docs)))
また
import operator
taglist = list(reduce(operator.or_, (set(d["tags"]) for d in docs)))
help(set.union)
教えてくれます
Help on method_descriptor:
union(...)
Return the union of sets as a new set.
(i.e. all elements that are in either set.)
明示的ではないのは、任意の数の引数を渡すことができ、すべてが結合されることです(おそらく、実装はコードを共有しset.update
、ヘルプは「それ自体と他の人の結合」を指します)。まったく言及されていませんが、真実は、引数は他のセットだけでなく、任意の反復可能である可能性があるということです。アルゴリズムについて考える場合、これは理にかなっています。2つのセットをマージする方法は実際にはありません。これは、一方を繰り返し処理して各要素をもう一方に追加するよりも優れています。
したがって、驚くほどシンプルで説明的な作業を行うことができます。
list(set().union(*(d['tags'] for d in docs)))
これは、コンストラクター(受け入れない)itertools.chain
の引数を一緒にするよりも少し明示的であり、私の好みになります。set
*args
(ネストされた内包表記の動作には少し慣れが必要ですが、ネストされたセット内包表記のアプローチも非常に気に入っています。)