dicts-python动态编程
我有一个dicts-python动态编程,python,combinations,dynamic-programming,Python,Combinations,Dynamic Programming,我有一个清单的dicts;我使用itertools.combinations获取索引和索引组合 list_of_dict = [{1: 'a', 2:'b', 3: 'c', 4: 'd'}, {1: 'b', 2:'b', 3: 'a', 4: 'd'}, {1: 'a', 2:'c', 3: 'd', 4: 'd'}, {1: 'c', 2:'a', 3: 'd', 4: 'b'}] indic
清单
的dict
s;我使用itertools.combinations
获取索引和索引组合
list_of_dict = [{1: 'a', 2:'b', 3: 'c', 4: 'd'},
{1: 'b', 2:'b', 3: 'a', 4: 'd'},
{1: 'a', 2:'c', 3: 'd', 4: 'd'},
{1: 'c', 2:'a', 3: 'd', 4: 'b'}]
indices = [0, 1, 2, 3]
combinations = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3),
(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3),
(0, 1, 2, 3)]
现在我定义了一个merge
函数,它接受2个dict
s,实现我的合并逻辑并返回一个dict
。我对组合的所有元素执行合并
list_of_dict = [{1: 'a', 2:'b', 3: 'c', 4: 'd'},
{1: 'b', 2:'b', 3: 'a', 4: 'd'},
{1: 'a', 2:'c', 3: 'd', 4: 'd'},
{1: 'c', 2:'a', 3: 'd', 4: 'b'}]
indices = [0, 1, 2, 3]
combinations = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3),
(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3),
(0, 1, 2, 3)]
对merge
的调用如下:
candidates = {}
for p in combinations:
n = 1
temp_p = None
c = None
while (n < (len(p) - 2)):
c = tuple(list(p)[0:-n])
if c in candidates:
temp_p = candidates[c]
break
else:
n += 1
if temp_p:
p1 = temp_p
p2 = p[len(c)]
candidate[p] = merge(list_of_dict[p1], list_of_dict[p2])
else:
candidates[p] = merge(list_of_dict[p[0]], list_of_dict[p[1]])
candidates={}
对于组合中的p:
n=1
温度p=无
c=无
而(n<(len(p)-2)):
c=元组(列表(p)[0:-n])
如果候选人中有c:
temp_p=候选人[c]
打破
其他:
n+=1
如果温度为:
p1=温度
p2=p[len(c)]
候选[p]=合并(目录[p1]的目录[U],目录[p2]的目录[U])
其他:
候选者[p]=合并(主语[p[0]]的列表,主语[p[1]]的列表)
逻辑:如我们所见,当我计算merge(0,1,2)
时,我可以重用merge(0,1)
的输出;i、 e.merge(0,1,2)=merge(merge(0,1,2)
。类似地,对于merge(0,1,2,3)
我可以重用merge(0,1,2)
问题:
我不能完全确定上面的代码块是否正确
“逻辑”中描述的内容李>
有没有一种优雅而有效的方法来实现上述目标
编辑:
合并函数执行以下操作。
如果d1[k]==d2[k],则将d1[k]添加到要返回的新dict中,否则不添加任何内容。
因此,根据给出的示例:
merge(0,1)
应该返回:{1:None,2:b',3:None,4:d'}
及
merge(0,1,2)
变成mergemerge({1:None,2:b',3:None,4:d'},{1:a',2:c',3:d',4:d'})
并且应该返回{1:None,2:None,3:None,4:d'}
这个过程一直持续到所有DICT的组合被合并
当我们不知道提交给算法的此类词典的初始数量时,这个问题尤为重要。此代码将满足您的所有要求:
from collections import defaultdict
def merge(d1, d2, *dicts):
new_dict = defaultdict()
new_dict.update(d1.copy())
for key, value in d2.items():
if value != new_dict[key]:
new_dict[key] = None
if dicts:
new_dict = merge(new_dict, *dicts)
return new_dict
for comb in combinations:
print(merge(*map(list_of_dict.__getitem__, comb)))
首先,我将传递字典留给了merge
,因为dict
是可变对象,所以在这种情况下,只有它在内存中的引用被传递给函数。您可以使用id
功能轻松检查它。所以,由于这个解决方案比按索引从列表中收集字典更具可读性,所以它更具python风格
其次,我使用了传递给merge
的第一个字典的copy
,所以对于其他组合,原始字典保持不变
正如您所看到的,我使用了collections
包中的defaultdict
,而不是dict
,因此如果您的d1
和d2
有不同的键,您可以跳过检查new\u dict
中是否存在键
最后一个:map(list\u of dict.\uu getitem\uuu,comb)
-这将返回生成器对象(对于python 3.x),其中包含来自list\u of dict
的项,这些项在comb
中索引。(*)map
之前的通配符意味着将其解包为参数,因此,在不实际创建新列表或元组(并在之后解包)的情况下,它只会将项(在本例中是对列表中字典的引用)作为merge
参数生成
就这样
提供的代码将打印以下内容:
defaultdict(None, {1: None, 2: 'b', 3: None, 4: 'd'})
defaultdict(None, {1: 'a', 2: None, 3: None, 4: 'd'})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
defaultdict(None, {1: None, 2: None, 3: None, 4: 'd'})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
defaultdict(None, {1: None, 2: None, 3: 'd', 4: None})
defaultdict(None, {1: None, 2: None, 3: None, 4: 'd'})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
defaultdict(None, {1: None, 2: None, 3: None, 4: None})
此外,我已经在20个字典(每个字典len=10000)的列表上测试了这段代码,我还有下一个计时:
生成目录列表:15.96887145599976
对每个索引组合应用合并(总共1012个):15.6302346700349
你的合并到底在做什么?你能展示一下函数的定义吗?另外,在这个示例中,您期望的输出是什么?@YaroslavSurzhikov添加了merge的描述和一个示例输出。提前感谢您的帮助:-)我会尽快更新我的答案以满足您的要求。顺便说一句,这对merge
accept indicies as agment很重要,还是像我已经实现的那样,它们可以是字典?字典的实际大小太大,因此我在实现中使用了索引。再次感谢你!嘿,我刚刚用解释更新了我的答案。对不起,如果你遇到错误,英语不是我的母语谢谢你的详细解释!那真的很有帮助@okkhoy很高兴我能帮上忙