【问题标题】:Python - intersection between a list and keys of a dictionaryPython - 列表和字典键之间的交集
【发布时间】:2012-06-24 20:11:38
【问题描述】:

我有一个如下所示的列表:

l1 = ['200:200', '90:728']

我有一本像这样的字典:

d1 = {'200:200':{'foo':'bar'},'300:300':{'foo':'bar'}}

我需要过滤掉只有键在 l1 中的字典。字典应该是这样的:

result = {'200:200':{'foo':'bar'}}

本质上是列表和字典键的交集,同时返回字典的小节。

如果时间对于大型系列来说是个问题,我如何有效地做到这一点?

谢谢

【问题讨论】:

    标签: python


    【解决方案1】:

    您可以使用以下代码:

    keys = set(l1).intersection(set(d1.keys()))
    result = {k:d1[k] for k in keys}
    

    编辑:正如评论者所建议的,您可以在 Python 2.x 中将第一行替换为:

    keys = set(l1).intersection(d1)
    

    在 Python 3.x 中:

    keys = d1.keys() & l1
    

    【讨论】:

    • 请注意,在 3.x 中,字典视图是类似集合的,因此您不需要将其包装在 set() 中。事实上,在 3.x 中,整个顶行可以是keys = d1.keys() & l1
    • @Lattyware 您也不需要将其转换为 2.x 中的集合
    • 甚至不需要keys(),set(l1).intersection(d1)
    • 并且不包装 d1.keys() 的好处是,如果 d1 很大,您将不会是 O(len(d1))。
    • 在 3.x 中,keys() 调用不需要任何费用,值得注意的是 - 因为它只是创建了一个 dict 视图。我已经在我的回答中显示了。
    【解决方案2】:

    在 3.x 中,这可以很简单:

    >>> {k: d1[k] for k in (d1.keys() & l1)}
    {'200:200': {'foo': 'bar'}}
    

    在 2.7 下,您可以使用 dict.viewkeys() 重新创建此功能:

    >>> {k: d1[k] for k in (d1.viewkeys() & l1)}
    {'200:200': {'foo': 'bar'}}
    

    在旧版本的 2.x 下,它有点冗长:

    >>> {k: d1[k] for k in (set(d1).intersection(l1))}
    {'200:200': {'foo': 'bar'}}
    

    【讨论】:

      【解决方案3】:

      不确定每种解决方案的性能,但我会这样做:

      {k: v for k, v in d1.items() if k in l1}
      

      【讨论】:

      • 即使 l1 的成员不是 d1 中的键,这也可以工作,许多其他人会失败。
      【解决方案4】:

      定义高效。无论如何,这就是我会做的。如果速度太慢,我可能会将其移至 Cython。

      s1 = set(l1)
      s2 = set(d1.keys())
      s3 = s1 & s2
      # now you can access d1 using only keys in s3, or construct a new dict if you like
      d2 = dict([(k,d1[k]) for k in s3])
      

      【讨论】:

        【解决方案5】:

        如果内存分配和释放导致此过程耗时过长,请使用 itertools 进行救援。

        import itertools
        result = {dict_key:d1[dict_key] for dict_key in itertools.ifilter(lambda list_item: list_item in d1, l1) }
        

        这不会为整个新集合不必要地分配内存,并且 l1 可以很容易地成为迭代器而不是列表。

        【讨论】:

          【解决方案6】:

          您可以在 dict 构造函数中使用列表推导:

          result = dict([(k,d1[k]) for k in l1 if k in d1])
          

          如果您担心删除重复键,请先将 l1 设置为集合:

          result = dict([(k,d1[k]) for k in set(l1) if k in d1])
          

          【讨论】:

          • 另请注意,您可以像在我的解决方案中那样执行 dict 生成器表达式。所以{k:v for k,v in arr}。这甚至有处理重复的好处。
          • @JPvdMerwe 这是一个字典推导,不是字典生成器表达式 - 生成器表达式是惰性的,字典推导不是。
          • @Lattyware:我知道我应该检查文档以正确使用我的术语。我的立场是正确的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-02-06
          • 2020-12-07
          • 2015-07-10
          • 1970-01-01
          • 1970-01-01
          • 2015-10-29
          相关资源
          最近更新 更多