2

キーごとに 3 つの float 値を追跡する辞書がいくつかあるとします (サブ辞書内)。複数の辞書に存在するキーの値を追加する方法で、これらの辞書をマージできるようにする必要があります。

通常の dict update では、値が上書きされるため、サブクラス化します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()これで、これらのキーと値のペアを1 つずつ追加するか、StatementDict.update()メソッドを使用できるようになります。ソース dict が 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}

dict を 2 番目の順序で追加すると、最初に配置された dict の値が 2 倍になるようです (2 回追加しますか?)。なぜこれが起こるのかわかりません。追加の順序に関係なく、目的の追加動作を確実に発生させるにはどうすればよいですか?

私が理解していないもう1つのこと:新しいものを作成して同じ値で埋めると、値が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

PS 私の実際のデータを使用すると、加算はまったく行われません。代わりに、最初に配置された値が保持されます。これは、値が上書きされる通常の dict の更新と同じではありません。残念ながら、小さなテスト データではこの動作を再現できませんでした。

4

1 に答える 1