0

如何制作以下代码片段“pythonic”

 tag_list = []
 for d in docs:
        tags = d["tags"]
        for tag in tags:
            if tag not in tag_list:
                tag_list.append(tag)
4

3 回答 3

10

在 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).

于 2012-05-29T23:37:59.620 回答
6
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)))
于 2012-05-29T23:35:51.700 回答
2

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

(我也很喜欢嵌套集合推导方法,尽管嵌套推导的工作方式需要一点时间来适应。)

于 2012-05-30T00:48:32.793 回答