[英]Adding default values to a list of ordered dict
python 3.8
给定一个OrderedDict
列表,为列表中所有OrderedList
中缺失的所有键设置默认值。 这必须保持顺序。
例子
def add_defaults(list_of_dicts, default_value):
#implementation goes here
pass
first = OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
second = OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k4', 'v4')])
third = OrderedDict([('k2', 'v2'), ('k5', 'v5'), ('k6', 'v6')])
lst=[first, second, third]
print(add_defaults(lst, ''))
预期 Output (格式化位以简化阅读):
[OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3'), ('k4', ''), ('k5', ''), ('k6', '')]),
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', ''), ('k4', 'v4'), ('k5', ''), ('k6', '')]),
OrderedDict([('k1', ''), ('k2', 'v2'), ('k3', ''), ('k4', ''), ('k5', 'v5'), ('k6', 'v6')])]
我的实现
def add_defaults(ordered_dict, default_value):
all_defaults=OrderedDict({}).fromkeys(
reduce(lambda k, v: OrderedDict(list(k.items()) + list(v.items())), ordered_dict, {}),
default_value
)
results = [OrderedDict(all_defaults) for _ in range(len(ordered_dict))]
for result, value in zip(results, ordered_dict):
result.update(value)
return results
问题
对于这样一个简单的任务,实现看起来过于复杂,而且看起来不像是最简单和 Pythonic 的解决方案。 实现它的惯用方式是什么?
似乎没有 escaping 首先查看所有字典,因为您需要知道要包含哪些键。 您可以通过按顺序将键传递给OrderedDict()
来更简单地做到这一点:
default = OrderedDict((k, val) for d in l for k in d.keys())
有了它,您可以混合列表中的字典:
def add_defaults(l, val):
default = OrderedDict((k, val) for d in l for k in d.keys())
return [OrderedDict({**default, **d}) for d in l]
first = OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
second = OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k4', 'v4')])
third = OrderedDict([('k2', 'v2'), ('k5', 'v5'), ('k6', 'v6')])
lst=[first, second, third]
print(add_defaults(lst, ''))
印刷:
[
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3'), ('k4', ''), ('k5', ''), ('k6', '')]),
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', ''), ('k4', 'v4'), ('k5', ''), ('k6', '')]),
OrderedDict([('k1', ''), ('k2', 'v2'), ('k3', ''), ('k4', ''), ('k5', 'v5'), ('k6', 'v6')])
]
是的,这太复杂了。 我只需一次通过即可获得密钥:
allkeys = [k for dct in lst for k in dct]
然后要创建新的有序字典,您可以遍历键并使用.get
和默认值:
result = [
OrderedDict( {k: dct.get(k, '') for k in allkeys } )
for dct in lst
]
所以,一些一般性的建议,接受还是放弃:
OrderedDict({}).fromkeys(...
您可以只使用OrderedDict.fromkeys(...
在构建新的数据结构时避免reduce
。 Python 的内置类型并不是为您可能会在 Scala 中遇到的那种函数式方法而设计的,该语言在构建时就考虑到了这一点(例如,列表的实现基本上是cons lists )。 您在这里引入了次优行为,使用串联作为归约操作,因为它会导致类似多项式时间的结果。 它也很冗长,迫使您创建中间列表。
OrderedDict(list(k.items()) + list(v.items()))
说到上面的 lambda,不要一味地使用 python 成语,所以k, v
应该指字典键值对,或者类似的东西。 在这里,它是两个字典,reduce 累加器和传入字典。 所以即使是这样的:
lambda acc, d: OrderedDict(list(acc.items()) + list(d.items()))
让读者更好地期待什么。
dict
对象还保留添加其键的顺序。 利用此功能,获取初始键列表:
>>> keys = {**first, **second, **third}.keys()
>>> # or
>>> key_d = {}
>>> for d in (first, second, third):
>>> key_d.update(d)
>>> keys = key_d.keys()
有趣的是,我们用这种方法得到了有序集的效果。 取一个dict
并添加键作为具有虚拟值的设置项,然后当您想知道集合中的内容时,只需抓住键即可。 它们将按添加的顺序排列。
使用dict.keys()
获得的 object 本身类似于集合并支持一些集合操作; 但是,您会丢失这些操作的顺序,所以first.keys() | second.keys() | third.keys()
first.keys() | second.keys() | third.keys()
first.keys() | second.keys() | third.keys()
将为我们提供键的联合,但不是按照它们在表达式中从左到右遇到的顺序。 然而, {**first, **second, **third}.keys()
为我们提供了这个“有序集”的并集 - 相同的效果(但按顺序),不同的语法。
一旦我们有了键,具有默认值的OrderedDict
就很容易创建。
>>> new_first = OrderedDict((k, first.get(k, '')) for k in keys)
>>> new_first
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3'), ('k4', ''),
('k5', ''), ('k6', '')])
从其他示例中,使用默认字典生成具有默认值的新字典是一个好主意。 这个默认字典实际上不必是OrderedDict
本身。
>>> default = {k: '' for d in d_list for k in d.keys()}
>>> new_first = {**default, **first}
new_first
现在具有给定顺序的所有键,其中first
缺失的键具有默认值。 new_first
已经是一个“有序字典”,但如果我们必须将它专门转换为OrderedDict
:
>>> new_first = OrderedDict(new_first)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.