ホームページ >バックエンド開発 >Python チュートリアル >Python で 2 つの辞書を結合する方法の例を共有する

Python で 2 つの辞書を結合する方法の例を共有する

黄舟
黄舟オリジナル
2017-08-09 13:16:171355ブラウズ

辞書は、Python 言語の唯一のマッピング タイプです。次の記事では、Python で 2 つの辞書 (dict) をエレガントに結合する方法について主に説明します。コードが詳しく紹介されていますので、必要な方はぜひ参考にしてみてください。

はじめに

Dictionary は Python の最も強力なデータ型の 1 つです。この記事では、2 つの辞書 (dict) を結合する Python の関連コンテンツを詳しく紹介し、参考と学習のために共有します。では、詳しい紹介を見てみましょう。

2つの辞書をマージする1行のコード

2つの辞書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 を使用している人には、より洗練された方法がありますが、それには 2 行のコードが必要です。


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

上記の方法では、yがxの内容を上書きするので、最終的な結果はb=3になります

python3.5を使わずに一行で完成させる方法

If 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

次に、1 行のコードを記述します。呼び出しを完了します:


 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())

これは実際にメモリ内に 2 つのリストを作成し、その後 3 番目のリストを作成します。コピーが完了したら、新しい辞書を作成し、最初の 3 つのリストを削除します。このメソッドはパフォーマンスを消費し、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() によって返されるリストに基づく Union メソッドも python3 では失敗します。さらに、union メソッドは繰り返される key の値に不確実性をもたらすため、優先順位の要件がある場合に使用します。 2 つの辞書をマージする場合、この方法はまったく不適切です。 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 が優先される例を示しますが、任意の順序で設定されているため、
 dict((k, v) for d in dicts for k, v in d.items())

の値は、前の 2 つのステップよりも非常に簡単です。メソッドですが、可読性が低く、Python 性が十分ではありません。キーが文字列でない場合は、やはり python3 での実行に失敗します


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

Guido Master van Rossum は次のように述べています: dict({}, {1:3}) は、結局のところメカニズムの悪用であるため、違法です。この方法はよりハック的ではありますが、あまりにもご都合主義的です。


パフォーマンスは低いがよりエレガントないくつかのメソッド


以下のメソッドは、パフォーマンスは低いですが、items メソッドよりもはるかに優れています。そして優先順位をサポートします。

>>> 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
Python2.6 では、これを行うことができます

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

itertools.chain は、キーと値のペアのイテレータを正しい順序でチェーンします:


rrreee


パフォーマンス テスト

以下は、Python 2.7 (システム Python) の Ubuntu 14.04 で実行されました。

以上がPython で 2 つの辞書を結合する方法の例を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。