假设您有几个字典可以记录每个键的三个浮点值(在子字典中)。您希望能够以添加多个字段中存在的密钥值的方式来合并这些字典。Python:为什么每个按键添加字典值取决于顺序?
对于普通的字典更新,值将被覆盖,所以你继承dict()
:
class StatementDict(dict):
def add(self, statement):
ann_id = statement[0]
lvl_dict = statement[1]
if ann_id in self:
self[ann_id]['skill'] += lvl_dict['skill']
self[ann_id]['knowledge'] += lvl_dict['knowledge']
self[ann_id]['interest'] += lvl_dict['interest']
else:
self[ann_id] = lvl_dict
def update(self, statement_dict):
for statement in statement_dict.iteritems():
self.add(statement)
然后你把你想合并/加入到一个普通字典的键类型的字典:
# Small example data that reproduces the error
few_statements = {}
few_statements['linkedin'] = {u'Homerun': {u'skill': 14.0,
u'knowledge': 34.0,
u'interest': 20.0}}
few_statements['tudelft'] = {u'Presentation': {u'skill': 14.0,
u'knowledge': 34.0,
u'interest': 20.0},
u'Future': {u'skill': 16.0,
u'knowledge': 25.33,
u'interest': 2.0},
u'Visual_perception': {u'skill': 20.46,
u'knowledge': 28.35,
u'interest': 4.0}}
few_statements['website'] = {u'Homerun': {u'skill': 1.0,
u'knowledge': 3.0,
u'interest': 2.0}}
few_statements['shareworks'] = {u'Presentation': {u'skill': 8.0,
u'knowledge': 20.0,
u'interest': 12.0},
u'Future': {u'skill': 17.0,
u'knowledge': 26.33,
u'interest': 3.0},
u'Visual_perception': {u'skill': 2.0,
u'knowledge': 3.0,
u'interest': 6.0}}
现在我们应该能够将这些键值对逐个添加到StatementDict()
,或者使用StatementDict.update()
方法。对于结果,将源字典添加到StatementDict的顺序无关紧要。
# First we try updating in one order
small_test1a = StatementDict()
for origin in ("tudelft", "website", "linkedin", "shareworks"):
for st in few_statements[origin].iteritems():
small_test1a.add(st)
# And then in another order
small_test2 = StatementDict()
for origin in ("linkedin", "shareworks", "tudelft", "website"):
for st in few_statements[origin].iteritems():
small_test2.add(st)
print "Different order, same result?", small_test1a == small_test2
# False, but why?
for key in small_test1a:
print "Desired:", key, small_test1a[key]
print "Unexpected:", key, small_test2[key]
唉,添加指令的顺序确实会影响结果。但是,为什么,以及意外结果发生了什么?
Desired: Future {u'skill': 33.0, u'knowledge': 51.66, u'interest': 5.0}
Unexpected: Future {u'skill': 50.0, u'knowledge': 77.99, u'interest': 8.0}
Desired: Presentation {u'skill': 22.0, u'knowledge': 54.0, u'interest': 32.0}
Unexpected: Presentation {u'skill': 30.0, u'knowledge': 74.0, u'interest': 44.0}
Desired: Homerun {u'skill': 15.0, u'knowledge': 37.0, u'interest': 22.0}
Unexpected: Homerun {u'skill': 29.0, u'knowledge': 71.0, u'interest': 42.0}
Desired: Visual_perception {u'skill': 22.46, u'knowledge': 31.35, u'interest': 10.0}
Unexpected: Visual_perception {u'skill': 24.46, u'knowledge': 34.35, u'interest': 16.0}
添加类型的字典中二阶似乎加倍值(增加了他们两次?),这是第一次放在字典的。我不明白为什么会发生这种情况。我如何获得所需的附加行为可靠发生,与添加顺序无关?
另一件我不明白的事情:为什么small_test1a
的值会在我制作新的StatementDict()
时发生变化并填充相同的值?
运行下面的线引起small_test1a
在循环的最后一次迭代改变:
small_test1b = StatementDict()
for origin in ("tudelft", "website", "linkedin", "shareworks"):
small_test1b.update(few_statements[origin])
print "\nDoes .update() function?", small_test1a == small_test1b
print small_test1a
P.S.使用我的实际数据,根本不会发生任何增加。相反,保留了第一个放置的值。这是而不是与更新普通字典相同,其中值被覆盖。不幸的是,我无法用小的测试数据重现这种行为。
谢谢你提醒我复制!我之前多次用字典犯了这个错误,所以我现在对自己有点失望了。 然而,使用'collections.defaultdict'似乎不那么简单。我试图将其子类化为'StatementDict(defaultdict(lvl_dict_factory))',其中'lvl_dict_factory = lambda:{'skill':0.0,'knowledge':0.0,'interest':0.0}',但这显然不是它的完成方式。 – AliOli
啊,这是调用它的错误方法。如果你有'class StatementDict(defaultdict)',你可以用例如'small_test1a = StatementDict(lvl_dict_factory)'创建一个实例。或者,提供你自己的'__init__',它可能会让你看起来更清晰;我将在一个示例中进行编辑。 – torek