>  기사  >  백엔드 개발  >  Python에서 두 개의 사전(dict)을 우아하게 병합하는 방법

Python에서 두 개의 사전(dict)을 우아하게 병합하는 방법

不言
不言원래의
2018-06-02 15:44:371724검색

Dictionary는 Python 언어의 유일한 매핑 유형입니다. 다음 기사에서는 Python에서 두 개의 사전(dict)을 우아하게 병합하는 방법에 대한 관련 정보를 주로 소개합니다. 코드가 아주 자세하게 소개되어 있으니 필요하신 분들은 참고하시면 됩니다.

머리말

사전은 Python에서 가장 강력한 데이터 유형 중 하나입니다. 이 기사에서는 두 사전(dict)을 병합하는 Python의 관련 내용을 자세히 소개하고 참고 및 학습을 위해 공유합니다. . 이제 설명은 이쯤 하고 자세한 소개를 살펴보겠습니다.

두 개의 사전을 병합하는 코드 한 줄

두 개의 사전 x와 y가 있다고 가정하고, x와 y의 값을 변경하지 않고 이를 새 사전으로 병합합니다. 예를 들어

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

새로운 결과 Z를 얻을 것으로 예상합니다. 키가 동일하면 y가 x를 덮습니다. 예상되는 결과는

>>> z
{'a': 1, 'b': 3, 'c': 4}

입니다. PEP448에는 새로운 구문을 구현할 수 있는데, 이 구문은 python3.5에서 지원됩니다. 병합된 코드는 다음과 같습니다

z = {**x, **y}

적절한 라인입니다. 코드. 많은 사람들이 여전히 python2를 사용하고 있기 때문에 python2 및 python3.0-python3.4를 사용하는 사람들을 위해 더 우아한 방법이 있지만 두 줄의 코드가 필요합니다.

z = x.copy()
z.update(y)

위 방법에서 y는 x의 내용을 덮으므로 최종 결과는 b=3입니다.

python3.5를 사용하지 않고 한 줄로 완성하는 방법

Python 3.5를 아직 사용하지 않았거나 이전 버전과 호환되는 코드를 작성해야 하고 단일 표현식으로 실행하려는 경우 가장 효율적인 방법은 함수에 넣는 것입니다:

def merge_two_dicts(x, y):
 """Given two dicts, merge them into a new dict as a shallow copy."""
 z = x.copy()
 z.update(y)
 return z

그런 다음 한 줄

 z = merge_two_dicts(x, y)

def merge_dicts(*dict_args):
 """
 Given any number of dicts, shallow copy and merge into a new dict,
 precedence goes to key value pairs in latter dicts.
 """
 result = {}
 for dictionary in dict_args:
 result.update(dictionary)
 return result

과 같이 여러 사전을 병합하는 함수를 정의할 수도 있습니다. 그런 다음 다음과 같이 사용할 수 있습니다.

z = merge_dicts(a, b, c, d, e, f, g)

, 동일한 키가 앞면 키를 덮습니다.

덜 우아한 데모

items

어떤 사람들은 다음 방법을 사용합니다.

 z = dict(x.items() + y.items())

이것은 실제로 메모리에 두 개의 목록을 만든 다음 세 번째 목록을 만드는 것입니다. 복사가 완료되면 새 사전을 만들고 처음 세 목록을 삭제합니다. 이 메서드는 성능을 소모하며 python3의 경우 items()가 객체를 반환하기 때문에 성공적으로 실행할 수 없습니다.

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: &#39;dict_items&#39; and 
&#39;dict_items&#39;

명시적으로 목록, z = dict(list(x.items()) + list(y.items())) 에 캐스팅해야 합니다. 이것도 마찬가지입니다. 성능 낭비. 또한 items()에서 반환된 목록을 기반으로 하는 통합 메서드는 python3에서도 실패합니다. 또한 통합 메서드는 반복되는 키 값에 불확실성을 초래하므로 우선순위 요구 사항이 있는 경우입니다. 두 개의 사전을 병합하는 경우 이 방법은 완전히 부적절합니다. z = dict(list(x.items()) + list(y.items())) ,这太浪费性能了。 另外,想以来于items()返回的list做并集的方法对于python3来说也会失败,而且,并集的方法,导致了重复的key在取值时的不确定,所以,如果你对两个dict合并有优先级的要求,这个方法就彻底不合适了。

>>> x = {&#39;a&#39;: []}
>>> y = {&#39;b&#39;: []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: &#39;list&#39;

这里有一个例子,其中y应该具有优先权,但是由于任意的集合顺序,x的值被保留:

>>> x = {&#39;a&#39;: 2}
>>> y = {&#39;a&#39;: 1}
>>> dict(x.items() | y.items())
{&#39;a&#39;: 2}

构造函数

也有人会这么用

z = dict(x, **y)

这样用很好,比前面的两步的方法高效多了,但是可阅读性差,不够pythonic,如果当key不是字符串的时候,python3中还是运行失败

>>> c = dict(a, **b)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

Guido van Rossum 大神说了:宣告dict({}, {1:3})

{k: v for d in dicts for k, v in d.items()}
다음은 y가 우선순위를 가져야 하지만 임의의 집합 순서로 인해 x의 값이 보존되는 예입니다.

 dict((k, v) for d in dicts for k, v in d.items())

Constructor

어떤 사람들은 이렇게 할 수도 있습니다.

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

을 사용하는 것이 매우 좋습니다. 이전 2단계 방법보다 훨씬 효율적이지만 가독성이 떨어지고 키가 문자열이 아닌 경우 Python3에서는 작업이 여전히 실패합니다.

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(),y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

Guido van Rossum이 말했습니다: dict({}, {1:3}) 선언은 결국 메커니즘 남용이기 때문에 불법입니다. 이 방법은 해커에 가깝지만 너무 기회주의적입니다.
성능은 좋지 않지만 더 우아한 일부 방법

다음 방법은 성능이 좋지는 않지만 항목 방법보다 훨씬 좋습니다. 그리고 우선순위를 지원합니다. ㅋㅋㅋ

성능 테스트

다음은 Python 2.7(시스템 Python)의 Ubuntu 14.04에서 수행되었습니다.

위 내용은 Python에서 두 개의 사전(dict)을 우아하게 병합하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.