[python] 두 개의 dicts (둘 다에 나타나는 키 값 추가)를 결합하는 파이썬적인 방법이 있습니까?

예를 들어 두 가지 dicts가 있습니다.

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

결과가 다음과 같이 두 가지 단어를 ‘결합’하는 파이썬적인 방법이 필요합니다.

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

즉, 키가 두 dicts에 모두 표시되면 값을 추가하고 하나의 dict에만 표시되면 해당 값을 유지하십시오.



답변

사용 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이므로 키와 값을 반복하는 것과 같이 일반적으로 해당 유형으로 수행하는 다른 모든 작업을 수행 할 수 있습니다.


답변

숫자가 아닌 값에도 적용되는보다 일반적인 솔루션 :

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}


답변

>>> 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}


답변

소개 :
(아마도) 최상의 솔루션이 있습니다. 그러나 당신은 그것을 알고 그것을 기억해야하며 때로는 파이썬 버전이 너무 오래되었거나 문제가 될 수 있기를 바랍니다.

그런 다음 가장 ‘해킹 된’솔루션이 있습니다. 그것들은 위대하고 짧지 만 때로는 이해하고 읽고 기억하기가 어렵습니다.

그러나 바퀴를 재발 명하려는 대안이 있습니다. -왜 바퀴를 재발 명합니까? -일반적으로 학습하기에 좋은 방법이기 때문에 (때로는 이미 존재하는 도구가 원하는 것을 정확하게 수행하지 않거나 원하는 방식으로 수행하지 않기 때문에) 알고 있거나 모르는 경우 가장 쉬운 방법이기 때문입니다. 문제에 대한 완벽한 도구를 기억하지 마십시오.

그래서 나는 모듈 에서 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}

아마도 그것을 구현하는 다른 방법이있을 것입니다.이를 수행하는 도구가 이미 있지만 일이 기본적으로 어떻게 작동하는지 시각화하는 것이 좋습니다.


답변

myDict = {}
for k in itertools.chain(A.keys(), B.keys()):
    myDict[k] = A.get(k, 0)+B.get(k, 0)


답변

추가 수입품없는 분!

그것들은 EAFP (권한보다 용서를 구하는 것이 더 쉽다) 라는 pythonic 표준 입니다. 아래 코드는 해당 파이썬 표준을 기반으로합니다 .

# 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 에게 감사드립니다 .


답변

확실히 Counter()s를 합산하는 것은 그러한 경우에 가장 파이썬적인 방법이지만 양의 값을 얻는 경우에만 가능합니다 . 다음은 예이며 사전 에서의 값을 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() 이는 입력 및 출력 모두 마이너스 제로 값을 허용한다.
  • 다중 집합 방법은 양수 값을 가진 사용 사례에 대해서만 설계되었습니다. 입력은 음수이거나 0 일 수 있지만 양수 값의 출력 만 작성됩니다. 유형 제한은 없지만 값 유형은 더하기, 빼기 및 비교를 지원해야합니다.
  • elements()방법에는 정수 카운트가 필요합니다. 0과 음수를 무시합니다.

따라서 카운터를 합산 한 후 그 문제를 해결 Counter.update하기 위해 원하는 출력을 얻기 위해 사용할 수 있습니다 . 그것은 작동 dict.update()하지만 카운트 대신에 카운트를 추가합니다.

In [24]: A.update(B)

In [25]: A
Out[25]: Counter({'d': 5, 'b': 5, 'a': 1, 'c': -1})