如何制作以下代码片段“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))))
或(感谢@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
,帮助指的是“自身和其他人的联合”)。根本没有提到但真实的是,参数可以是任何可迭代的,而不仅仅是其他集合。如果您考虑算法,这是有道理的;没有一种方法可以合并两个集合,这比仅迭代一个集合并将每个元素添加到另一个集合更好。
因此,我们可以用非常简单和描述性的方式来完成这项工作:
list(set().union(*(d['tags'] for d in docs)))
这比构造函数(不接受)itertools.chain
的 ing 参数更明确一些,这使它成为我的首选。set
*args
(我也很喜欢嵌套集合推导方法,尽管嵌套推导的工作方式需要一点时间来适应。)