Python 将默认值添加到有序dict列表
Python 将默认值添加到有序dict列表,python,python-3.x,Python,Python 3.x,python 3.8 给定一个OrderedDicts列表,为列表中所有OrderedLists中缺少的所有键设置默认值。必须这样做才能保留订单。 示例 def add_defaults(list_of_dicts, default_value): #implementation goes here pass first = OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')]) second = OrderedDict(
python 3.8
给定一个OrderedDict
s列表,为列表中所有OrderedList
s中缺少的所有键设置默认值。必须这样做才能保留订单。
示例
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, ''))
预期输出(稍微格式化以简化阅读):
我的实施
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解决方案。实现它的惯用方法是什么?首先查看所有的dict似乎是不可避免的,因为您需要知道要包含哪些键。只需将键按所示顺序传递到
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')])
]
看起来没有办法不先看一遍所有的字典,因为你需要知道应该包括哪些键。只需将键按所示顺序传递到
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]
然后,要创建新的有序dict,您需要在键上迭代,并使用默认值。get
:
result = [
OrderedDict( {k: dct.get(k, '') for k in allkeys } )
for dct in lst
]
所以,一些一般性的建议,要么接受,要么放弃:
您只需使用
OrderedDict.fromkeys(…
在构建新的数据结构时,避免使用
reduce
。Python的内置类型并不是为您在Scala中可能遇到的那种函数式方法而设计的,在Scala中,语言就是基于这一点构建的(例如,列表的实现)。您在这里引入了次优行为,使用串联作为缩减操作,因为这将导致类似多项式时间的结果。它也非常冗长,迫使您创建中间列表
OrderedDict(list(k.items()) + list(v.items()))
说到上面的lambda,不要随意使用python习语,因此
k,v
应该指字典键值对,或者类似的东西。这里有两个字典,reduce累加器和传入dict。甚至类似于:
lambda acc, d: OrderedDict(list(acc.items()) + list(d.items()))
为读者提供更好的信息。是的,这太复杂了。我只需做一次简单的操作就可以拿到钥匙:
allkeys = [k for dct in lst for k in dct]
然后,要创建新的有序dict,您需要在键上迭代,并使用默认值。get
:
result = [
OrderedDict( {k: dct.get(k, '') for k in allkeys } )
for dct in lst
]
所以,一些一般性的建议,要么接受,要么放弃:
您只需使用
OrderedDict.fromkeys(…
在构建新的数据结构时,避免使用
reduce
。Python的内置类型并不是为您在Scala中可能遇到的那种函数式方法而设计的,在Scala中,语言就是基于这一点构建的(例如,列表的实现)。您在这里引入了次优行为,使用串联作为缩减操作,因为这将导致类似多项式时间的结果。它也非常冗长,迫使您创建中间列表
OrderedDict(list(k.items()) + list(v.items()))
说到上面的lambda,不要随意使用python习语,因此
k,v
应该指字典键值对,或者类似的东西。这里有两个字典,reduce累加器和传入dict。甚至类似于:
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()
获得的对象本身设置为like,并支持一些set操作;但是,您失去了这些操作的顺序,因此首先。keys()|第二。keys()|第三。keys()
将为我们提供键的并集,但不是按照表达式中从左到右遇到的顺序。但是,{**first,**second,**third}.keys()
给出了这个“有序集”按顺序的并集-相同的效果(但按顺序),不同的语法
一旦我们有了这些键,OrderedDict
s和默认值就很容易创建了
>>> 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\u first
现在具有给定顺序中的所有键,其中缺少first
的键具有默认值。new\u first
已经是一个“有序字典”,但如果我们必须将其专门转换为OrderedDict
:
>>> new_first = OrderedDict(new_first)
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()
获得的对象本身设置为like,并支持一些set操作;但是,您失去了这些操作的顺序,因此首先。keys()|第二。keys()|第三。keys()
将为我们提供键的并集,但不是按照表达式中从左到右遇到的顺序。但是,{**first,**second,**third}.keys()
给出了这个“有序集”按顺序的并集-相同的效果(但按顺序),不同的语法
一旦我们有了这些键,OrderedDict
s和默认值就很容易创建了
>>> new_first = OrderedDict((k, first.get(k, '')) for k in keys)
>>> new_first
OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3'), ('k4', ''),
('k5', ''), ('k6', '')])
从t