【问题标题】:Subset fields from an ordereddict?来自有序字典的子集字段?
【发布时间】:2016-10-31 01:45:01
【问题描述】:

所以,我有一个有序字典,它有一堆键/值对。我可以使用 items() 方法提取所有它们。但是,如果我只想选择其中一些呢?

>>> import collections
>>> d = collections.OrderedDict({'banana': 3, 'apple': 4, 'pear': 1,'orange': 2})
>>> d.items()
[('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]

如果我只想要苹果和香蕉怎么办?

有没有办法指定我想要的键?

>>> d['apple','banana'] <-- does not work

我正在考虑在最后使用列表推导来过滤结果,但看起来很乱,我希望有更好的方法。

【问题讨论】:

  • 您希望d['apple','banana'] 制作什么?
  • 元组或键/值对的列表,与 .items() 相同。

标签: python ordereddictionary


【解决方案1】:

你可以定义一个单行来做到这一点:

>>> import collections
>>> d = collections.OrderedDict({'banana': 3, 'apple': 4, 'pear': 1,'orange': 2})
>>> d.items()
[('orange', 2), ('pear', 1), ('banana', 3), ('apple', 4)]
>>>
>>> subset = lambda d, *keys: [(key, d[key]) for key in keys]
>>> subset(d, 'apple', 'banana')
[('apple', 4), ('banana', 3)]

作为奖励,它也适用于常规 dict 对象。

更新

要获得与OrderedDict 相同顺序的结果列表,正如@Maxim Veksler 似乎认为您可能想要的那样,必须以一种给定特定顺序的方式定义有序字典。在 3.6 之前的 Python 版本中,必须做这样的事情,而不是你的问题:

d = collections.OrderedDict([('banana', 3), ('apple', 4), ('pear', 1), ('orange', 2)])

它将list 参数传递给构造函数,而不是常规的dict

所以假设已经完成(或者如果您使用的是 Python 3.6+ 则没有),您可以像这样定义 subset() 函数:

subset = lambda d, *keys: [(key, d[key]) for key in d.keys() if key in set(keys)]

给定正确创建的样本OrderedDict 输入,将返回此结果:

>>> subset(d, 'apple', 'banana')
[('banana', 3), ('apple', 4)]

请注意,返回列表中的对现在与 OrderedDict 中的键的顺序相同。

【讨论】:

  • 不会丢失 OrderedDict 想要保留的键的顺序吗?
  • @Maxim:OP 在问题中只字未提关于保持原始Orderedict 顺序的结果。查看他们对question 的回复,我在评论中询问了他们想要的结果。
【解决方案2】:

我不知道存在的方法,但如果这是您发现自己必须在整个代码库中完成的事情,那么创建一个通用方法可能是值得的。也许像

>>> specific_dict_items = lambda d, l: [(key, d.get(key, '')) for key in l]
>>> specific_dict_items({1:1, 2:2, 3:3, 4:4, 5:5}, [1, 3, 5, 7])
[(1, 1), (3, 3), (5, 5), (7, '')]

【讨论】:

    【解决方案3】:

    您很可能会以一种或另一种方式使用列表推导式。这是一种将列表推导式隐藏在方法实现中的方法:

    from collections import OrderedDict
    
    class MultOrderedDict(OrderedDict):
        def items(self, *items):
            all = super(MultOrderedDict, self).items()
            if not items:
                return all
            return type(self)((key, value) for (key, value) in all if key in items).items()
    

    使用该类定义(假设它在 multorddict.py 中),您可以执行以下操作:

    >>> from multorddict import MultOrderedDict
    >>> mod = MultOrderedDict(banana=3, apple=4, pear=1, orange=2)
    >>> mod.items()
    [('orange', 2), ('pear', 1), ('apple', 4), ('banana', 3)]
    >>> mod.items('apple','banana')
    [('apple', 4), ('banana', 3)]
    >>> 
    

    这种方法改变了items 方法的语义,这可能不是一件好事。

    【讨论】:

    • 这不会返回元组或键/值对的列表,与 items() 一样。执行mod['apple', 'banana']时也会无限递归。
    • 同意,我没有在 python2 中测试我的初始实现(它在 python3 中没有相同的问题)。如果答案未被接受,我会删除它,但我将其改写为覆盖items 而不是__getitem__。最终,熟悉列表推导并直接使用它们会更有意义。
    猜你喜欢
    • 2010-09-08
    • 2021-07-07
    • 2015-07-06
    • 1970-01-01
    • 2018-08-14
    • 2012-03-08
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    相关资源
    最近更新 更多