522

たとえば、私には2つの口述があります。

Dict A: {'a': 1, 'b': 2, 'c': 3}
Dict B: {'b': 3, 'c': 4, 'd': 5}

結果が次のようになるように、2つのdictを「組み合わせる」というpythonicな方法が必要です。

{'a': 1, 'b': 5, 'c': 7, 'd': 5}

つまり、キーが両方のdictに表示される場合は、それらの値を追加し、1つのdictにのみ表示される場合は、その値を保持します。

4

20 に答える 20

882

使用collections.Counter:

>>> from collections import Counter
>>> A = Counter({'a':1, 'b':2, 'c':3})
>>> B = Counter({'b':3, 'c':4, 'd':5})
>>> A + B
Counter({'c': 7, 'b': 5, 'd': 5, 'a': 1})

カウンターは基本的に のサブクラスでdictあるため、キーと値の反復処理など、通常そのタイプで行う他のすべてのことをカウンターで行うことができます。

于 2012-06-13T09:22:27.340 に答える
126

数値以外の値でも機能する、より一般的なソリューション:

a = {'a': 'foo', 'b':'bar', 'c': 'baz'}
b = {'a': 'spam', 'c':'ham', 'x': 'blah'}

r = dict(a.items() + b.items() +
    [(k, a[k] + b[k]) for k in set(b) & set(a)])

またはさらに一般的な:

def combine_dicts(a, b, op=operator.add):
    return dict(a.items() + b.items() +
        [(k, op(a[k], b[k])) for k in set(b) & set(a)])

例えば:

>>> a = {'a': 2, 'b':3, 'c':4}
>>> b = {'a': 5, 'c':6, 'x':7}

>>> import operator
>>> print combine_dicts(a, b, operator.mul)
{'a': 10, 'x': 7, 'c': 24, 'b': 3}
于 2012-06-13T09:41:10.647 に答える
72
>>> A = {'a':1, 'b':2, 'c':3}
>>> B = {'b':3, 'c':4, 'd':5}
>>> c = {x: A.get(x, 0) + B.get(x, 0) for x in set(A).union(B)}
>>> print(c)

{'a': 1, 'c': 7, 'b': 5, 'd': 5}
于 2012-06-13T09:25:28.460 に答える
47

はじめに: (おそらく) 最善の解決策があります。しかし、それを知って覚えておく必要があり、Python のバージョンが古すぎたり、問題が発生したりしないことを祈る必要がある場合もあります。

次に、最も「ハックな」ソリューションがあります。それらは素晴らしく短いものですが、理解するのも、読むのも、覚えるのも難しい場合があります。

ただし、車輪の再発明を試みるという代替手段があります。- なぜ車輪を再発明するのですか? - 一般的には、学習するのに非常に良い方法であるため (また、既存のツールが、あなたが望むことや希望する方法を正確に実行しない場合もあります)、または知らない場合や問題に最適なツールを覚えていません。

そこでCounter、モジュールからクラスの車輪を再発明することを提案しcollectionsます (少なくとも部分的には):

class MyDict(dict):
    def __add__(self, oth):
        r = self.copy()

        try:
            for key, val in oth.items():
                if key in r:
                    r[key] += val  # You can custom it here
                else:
                    r[key] = val
        except AttributeError:  # In case oth isn't a dict
            return NotImplemented  # The convention when a case isn't handled

        return r

a = MyDict({'a':1, 'b':2, 'c':3})
b = MyDict({'b':3, 'c':4, 'd':5})

print(a+b)  # Output {'a':1, 'b': 5, 'c': 7, 'd': 5}

それを実装する方法はおそらく他にもあり、それを行うためのツールはすでに存在しますが、物事が基本的にどのように機能するかを視覚化することは常に良いことです。

于 2013-02-18T06:45:45.547 に答える
16

確実に s を合計することCounter()は、そのような場合に行くための最も Pythonic な方法ですが、それが正の値になる場合に限られます。ここに例があります。ご覧のとおり、辞書で の値をc否定した後の結果はありません。cB

In [1]: from collections import Counter

In [2]: A = Counter({'a':1, 'b':2, 'c':3})

In [3]: B = Counter({'b':3, 'c':-4, 'd':5})

In [4]: A + B
Out[4]: Counter({'d': 5, 'b': 5, 'a': 1})

これは、Counters が主に正の整数を使用して実行中のカウントを表すように設計されているためです (負のカウントは無意味です)。ただし、これらのユースケースを支援するために、python は最小範囲と型の制限を次のように文書化しています。

  • Counter クラス自体は、キーと値に制限のないディクショナリ サブクラスです。値はカウントを表す数値を意図していますが、値フィールドには何でも格納できます。
  • このmost_common()メソッドは、値が順序付け可能であることのみを必要とします。
  • などのインプレース操作c[key] += 1の場合、値の型は加算と減算のみをサポートする必要があります。そのため、分数、浮動小数点数、および小数が機能し、負の値がサポートされます。入力と出力の両方に負の値とゼロの値を許可するupdate()andについても同じことが言えます。subtract()
  • multiset メソッドは、正の値を使用する場合のみに設計されています。入力は負またはゼロの場合がありますが、正の値を持つ出力のみが作成されます。型の制限はありませんが、値の型は加算、減算、および比較をサポートする必要があります。
  • メソッドにはelements()整数カウントが必要です。ゼロおよび負のカウントは無視されます。

したがって、カウンターを合計した後にその問題を回避するCounter.updateために、希望の出力を得るために使用できます。のように機能dict.update()しますが、カウントを置き換えるのではなく追加します。

In [24]: A.update(B)

In [25]: A
Out[25]: Counter({'d': 5, 'b': 5, 'a': 1, 'c': -1})
于 2017-03-10T11:12:15.363 に答える
12

余計な輸入は一切なし!

彼らは、EAFP (許可よりも許しを求める方が簡単)と呼ばれるpythonic標準です。以下のコードは、そのpython standardに基づいています。

# The A and B dictionaries
A = {'a': 1, 'b': 2, 'c': 3}
B = {'b': 3, 'c': 4, 'd': 5}

# The final dictionary. Will contain the final outputs.
newdict = {}

# Make sure every key of A and B get into the final dictionary 'newdict'.
newdict.update(A)
newdict.update(B)

# Iterate through each key of A.
for i in A.keys():

    # If same key exist on B, its values from A and B will add together and
    # get included in the final dictionary 'newdict'.
    try:
        addition = A[i] + B[i]
        newdict[i] = addition

    # If current key does not exist in dictionary B, it will give a KeyError,
    # catch it and continue looping.
    except KeyError:
        continue

編集: jerzykの改善提案に感謝します。

于 2014-05-03T06:20:57.897 に答える
11
import itertools
import collections

dictA = {'a':1, 'b':2, 'c':3}
dictB = {'b':3, 'c':4, 'd':5}

new_dict = collections.defaultdict(int)
# use dict.items() instead of dict.iteritems() for Python3
for k, v in itertools.chain(dictA.iteritems(), dictB.iteritems()):
    new_dict[k] += v

print dict(new_dict)

# OUTPUT
{'a': 1, 'c': 7, 'b': 5, 'd': 5}

また

@Martijnが上で述べたように、代わりにCounterを使用できます。

于 2014-07-04T10:49:33.167 に答える
7

より一般的で拡張可能な方法については、mergedictを確認してください。singledispatch型に基づいて値を使用およびマージできます。

例:

from mergedict import MergeDict

class SumDict(MergeDict):
    @MergeDict.dispatch(int)
    def merge_int(this, other):
        return this + other

d2 = SumDict({'a': 1, 'b': 'one'})
d2.merge({'a':2, 'b': 'two'})

assert d2 == {'a': 3, 'b': 'two'}
于 2014-11-14T10:43:41.230 に答える
5

Python 3.5 から: マージと合計

@tokeinizer_fsj のコメントで、質問の意味を完全には理解していないことを教えてくれたことに感謝します (追加とは、最終的に 2 つの辞書で異なるキーを追加することを意味すると考えていましたが、代わりに、共通のキー値を意味していました合計する必要があります)。そのため、マージの前にそのループを追加して、2 番目の辞書に共通キーの合計が含まれるようにしました。最後のディクショナリは、2 つのマージの結果である新しいディクショナリで値が保持されるものになるため、問題は解決したと思います。このソリューションは、python 3.5 以降のバージョンから有効です。

a = {
    "a": 1,
    "b": 2,
    "c": 3
}

b = {
    "a": 2,
    "b": 3,
    "d": 5
}

# Python 3.5

for key in b:
    if key in a:
        b[key] = b[key] + a[key]

c = {**a, **b}
print(c)

>>> c
{'a': 3, 'b': 5, 'c': 3, 'd': 5}

再利用可能なコード

a = {'a': 1, 'b': 2, 'c': 3}
b = {'b': 3, 'c': 4, 'd': 5}


def mergsum(a, b):
    for k in b:
        if k in a:
            b[k] = b[k] + a[k]
    c = {**a, **b}
    return c


print(mergsum(a, b))
于 2016-08-28T09:47:37.807 に答える
1

このソリューションは使いやすく、通常の辞書として使用されますが、sum 関数を使用できます。

class SumDict(dict):
    def __add__(self, y):
        return {x: self.get(x, 0) + y.get(x, 0) for x in set(self).union(y)}

A = SumDict({'a': 1, 'c': 2})
B = SumDict({'b': 3, 'c': 4})  # Also works: B = {'b': 3, 'c': 4}
print(A + B)  # OUTPUT {'a': 1, 'b': 3, 'c': 6}
于 2016-12-09T14:26:10.313 に答える
1

1行の解決策は、辞書内包表記を使用することです。

C = { k: A.get(k,0) + B.get(k,0) for k in list(B.keys()) + list(A.keys()) }
于 2021-09-12T02:46:47.867 に答える
-1

他のモジュールやライブラリなしで 3 つの辞書 a、b、c を 1 行にマージする

3つの辞書がある場合

a = {"a":9}
b = {"b":7}
c = {'b': 2, 'd': 90}

すべてを 1 行でマージし、次を使用して dict オブジェクトを返します

c = dict(a.items() + b.items() + c.items())

戻る

{'a': 9, 'b': 2, 'd': 90}
于 2017-11-17T09:18:43.127 に答える