programing

두 개의 dicts(양쪽에 나타나는 키의 값을 추가하는)를 조합하는 피토닉 방법이 있습니까?

bestcode 2022. 9. 5. 23:03
반응형

두 개의 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}

즉, 키가 두 dict에 모두 나타나면 값을 추가하고, 키가 한 dict에만 나타나면 값을 유지합니다.

사용방법:

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

인트로: (아마도) 최적의 솔루션이 있습니다.그러나 당신은 그것을 알고 기억해야 하며 때때로 당신은 당신의 Python 버전이 너무 오래되거나 문제가 되지 않기를 바라야 한다.

그리고 가장 '해키한' 솔루션이 있습니다.그것들은 훌륭하고 짧지만 때때로 이해하기 어렵고, 읽기도 어렵고, 기억하기도 어렵다.

단, 바퀴를 재창조하는 대안은 있습니다.-왜 바퀴를 재창조하는가?-일반적으로 그것은 학습에 매우 좋은 방법이기 때문입니다(기존 툴이 원하는 대로 또는 원하는 방식으로 동작하지 않기 때문이기도 합니다).완벽한 방법을 모르거나 기억하지 못하는 경우에는 가장 쉬운 방법입니다.툴이 준비되어 있습니다.

그래서, 저는 이 바퀴를 재창조할 것을 제안합니다.Countercollections모적적적적적 ( 。

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}

다른 방법으로 구현할 수도 있고 이미 툴이 있지만 기본적으로 어떻게 작동하는지 시각화하는 것은 항상 좋은 일입니다.

★★★★★★★★★★★★★★★★★★★의 합계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})

그 이유는Counter는 주로 실행 카운트를 나타내기 위해 양의 정수로 작동하도록 설계되었습니다(음수 카운트는 무의미함).그러나 이러한 사용 사례를 지원하기 위해 python에서는 다음과 같이 최소 범위 및 유형 제한을 문서화합니다.

  • 카운터 클래스 자체는 키와 값에 제한이 없는 사전 하위 클래스입니다.값은 카운트를 나타내는 숫자이지만 값 필드에는 모든 값을 저장할 수 있습니다.
  • most_common()방법
  • 다음과 같은 인플레이스 운영의 경우c[key] += 1값 유형은 덧셈과 뺄셈만 지원하면 됩니다.따라서 분수, 부동 소수 및 소수점이 작동하며 음수 값이 지원됩니다.에 대해서도 마찬가지입니다.update() ★★★★★★★★★★★★★★★★★」subtract()입력과 출력 모두에 음수 및 0 값을 사용할 수 있습니다.
  • 멀티셋 방법은 양의 값을 가진 사용 사례에 대해서만 설계되었습니다.입력은 음수 또는 0일 수 있지만 양의 값을 가진 출력만 생성됩니다.유형 제한은 없지만 값 유형은 더하기, 빼기 및 비교를 지원해야 합니다.
  • elements()이치노제로 카운트와 마이너스 카운트를 무시합니다.

카운터를 한 후 이 ""를 사용할 수 .Counter.update이런 으로 동작합니다.dict.update()이치노

In [24]: A.update(B)

In [25]: A
Out[25]: Counter({'d': 5, 'b': 5, 'a': 1, 'c': -1})
myDict = {}
for k in itertools.chain(A.keys(), B.keys()):
    myDict[k] = A.get(k, 0)+B.get(k, 0)

추가 수입품 없는 거!

그것은 EAFP라고 불리는 비단뱀의 표준이다.아래 코드는 해당 python 표준을 기반으로 합니다.

# 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에게 감사한다.

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이 위에서 설명한 바와 같이 카운터를 사용할 수 있습니다.

보다 포괄적이고 확장 가능한 방법은 mergeict를 확인하십시오.사용하다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'}

.a.update( b ) a + b

from collections import Counter
a = Counter({'menu': 20, 'good': 15, 'happy': 10, 'bar': 5})
b = Counter({'menu': 1, 'good': 1, 'bar': 3})

%timeit a + b;
## 100000 loops, best of 3: 8.62 µs per loop
## The slowest run took 4.04 times longer than the fastest. This could mean that an intermediate result is being cached.

%timeit a.update(b)
## 100000 loops, best of 3: 4.51 µs per loop

Python 3.5부터: Marge 및 Summing

@tokeinizer_fsj가 질문의 의미를 완전히 이해하지 못했다고 코멘트에서 알려준 덕분에(add는 결국 두 사전에서 다른 곳에 키를 추가하는 것을 의미하고 대신 공통 키 값을 합산해야 한다는 것을 의미한다고 생각했습니다).두 번째 사전에는 공통 키의 합계가 포함되도록 병합 전에 루프를 추가했습니다.마지막 사전은 두 사전이 합쳐진 결과, 새로운 사전에서 가치가 지속되는 사전이 될 것이기 때문에 문제는 해결되었다고 생각합니다.이 솔루션은 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))

한 줄의 해결책은 사전 이해를 사용하는 것입니다.

C = { k: A.get(k,0) + B.get(k,0) for k in list(B.keys()) + list(A.keys()) }
def merge_with(f, xs, ys):
    xs = a_copy_of(xs) # dict(xs), maybe generalizable?
    for (y, v) in ys.iteritems():
        xs[y] = v if y not in xs else f(xs[x], v)

merge_with((lambda x, y: x + y), A, B)

이것은 간단하게 일반화할 수 있습니다.

def merge_dicts(f, *dicts):
    result = {}
    for d in dicts:
        for (k, v) in d.iteritems():
            result[k] = v if k not in result else f(result[k], v)

그 후, 임의의 수의 딕트를 사용할 수 있습니다.

이것은 두 사전을 병합하기 위한 간단한 솔루션입니다.+=사전에서 한 번만 반복해야 하기 때문에 값에 적용할 수 있습니다.

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

dicts = [{'b':3, 'c':4, 'd':5},
         {'c':9, 'a':9, 'd':9}]

def merge_dicts(merged,mergedfrom):
    for k,v in mergedfrom.items():
        if k in merged:
            merged[k] += v
        else:
            merged[k] = v
    return merged

for dct in dicts:
    a = merge_dicts(a,dct)
print (a)
#{'c': 16, 'b': 5, 'd': 14, 'a': 10}

이 솔루션은 사용하기 쉽고 일반 사전으로 사용되지만, 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}

위의 솔루션은 다음과 같은 몇 가지 시나리오가 있는 경우에 적합합니다.Counters. 단, 방대한 리스트가 있는 경우, 다음과 같은 것이 훨씬 좋습니다.

from collections import Counter

A = Counter({'a':1, 'b':2, 'c':3})
B = Counter({'b':3, 'c':4, 'd':5}) 
C = Counter({'a': 5, 'e':3})
list_of_counts = [A, B, C]

total = sum(list_of_counts, Counter())

print(total)
# Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})

위의 솔루션은 기본적으로 다음과 같은 사항을 요약한 것입니다.Counters 기준:

total = Counter()
for count in list_of_counts:
    total += count
print(total)
# Counter({'c': 7, 'a': 6, 'b': 5, 'd': 5, 'e': 3})

이것은 같은 일을 하지만 나는 그것이 아래에서 효과적으로 무엇을 하고 있는지 보는 것이 항상 도움이 된다고 생각한다.

그럼 어떻게 되는 거죠?

def dict_merge_and_sum( d1, d2 ):
    ret = d1
    ret.update({ k:v + d2[k] for k,v in d1.items() if k in d2 })
    ret.update({ k:v for k,v in d2.items() if k not in d1 })
    return ret

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

print( dict_merge_and_sum( A, B ) )

출력:

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

여기 사전적 이해를 사용하는 또 다른 옵션이 있습니다.dict():

dict3 = dict(dict1, **{ k: v + dict1.get(k, 0) for k, v in dict2.items() })
# {'a': 4, 'b': 2, 'c': 7, 'g': 1}

https://docs.python.org/3/library/stdtypes.html#dict 에서 :

https://docs.python.org/3/library/stdtypes.html#dict

그리고 또

키워드 인수를 지정하면 키워드 인수와 그 값이 positional 인수로 작성된 딕셔너리에 추가됩니다.

딕트 이해

**{ k: v + dict1.get(v, 0), v in dict2.items() }

핸들, dict1[1] 추가v우리는 명시적인 언급은 필요 없다.if여기에서는, 디폴트치가dict1.get대신 0으로 설정할 수 있습니다.

두 개의 dict를 조합하는 보다 일반적인 방법입니다.모듈이나 툴을 사용하는 것은 좋지만, 그 이면에 있는 논리를 이해하는 것은 툴을 기억하지 못하는 경우에 도움이 됩니다.

공통 키에 대한 값을 추가하는 두 개의 사전을 결합하는 프로그램입니다.

def combine_dict(d1,d2):

for key,value in d1.items():
  if key in d2:
    d2[key] += value
  else:
      d2[key] = value
return d2

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

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

여기 매우 일반적인 해결책이 있습니다.임의의 수의 dict + 키(일부 dict에만 있는 키)를 처리할 수 있습니다.또, 임의의 집약 기능을 간단하게 사용할 수 있습니다.

def aggregate_dicts(dicts, operation=sum):
    """Aggregate a sequence of dictionaries using `operation`."""
    all_keys = set().union(*[el.keys() for el in dicts])
    return {k: operation([dic.get(k, None) for dic in dicts]) for k in all_keys}

예:

dicts_same_keys = [{'x': 0, 'y': 1}, {'x': 1, 'y': 2}, {'x': 2, 'y': 3}]
aggregate_dicts(dicts_same_keys, operation=sum)
#{'x': 3, 'y': 6}

예를 들어 비표준 키 및 범용 집약:

dicts_diff_keys = [{'x': 0, 'y': 1}, {'x': 1, 'y': 2}, {'x': 2, 'y': 3, 'c': 4}]

def mean_no_none(l):
    l_no_none = [el for el in l if el is not None]
    return sum(l_no_none) / len(l_no_none)

aggregate_dicts(dicts_diff_keys, operation=mean_no_none)
# {'x': 1.0, 'c': 4.0, 'y': 2.0}
dict1 = {'a':1, 'b':2, 'c':3}
dict2 = {'a':3, 'g':1, 'c':4}
dict3 = {} # will store new values

for x in dict1:
    
    if x in dict2: #sum values with same key
        dict3[x] = dict1[x] +dict2[x]
    else: #add the values from x to dict1
        dict3[x] = dict1[x]
        
#search for new values not in a
for x in dict2:
    if x not in dict1:
        dict3[x] = dict2[x]
print(dict3) # {'a': 4, 'b': 2, 'c': 7, 'g': 1}

다른 모듈이나 lib 없이 3개의 dict a, b, c를 한 줄에 병합할 수 있습니다.

만약 우리가 3개의 딕트를 가지고 있다면

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

모두 한 줄로 병합하고 다음 명령을 사용하여 dict 개체 반환

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

돌아오는

{'a': 9, 'b': 2, 'd': 90}

언급URL : https://stackoverflow.com/questions/11011756/is-there-any-pythonic-way-to-combine-two-dicts-adding-values-for-keys-that-appe

반응형