Pythonで辞書をコピーする高速な方法


92

私は辞書をよく使うPythonプログラムを持っています。辞書のコピーを何千回も作成する必要があります。キーと関連コンテンツの両方のコピーが必要です。コピーは編集されるため、オリジナルにリンクすることはできません(たとえば、コピーの変更がオリジナルに影響してはなりません)。

キーは文字列、値は整数(0/1)です。

私は現在、簡単な方法を使用しています:

newDict = oldDict.copy()

コードをプロファイリングすると、コピー操作にほとんどの時間がかかることがわかります。

このdict.copy()方法に代わる高速な方法はありますか?何が最速でしょうか?


1
値が0または1のいずれかであるbool場合、int?は?
Samir Talwar、

5
そして、それらの何千ものコピーが必要な場合、ビットマスクはさらにうまく機能しますか?
Wooble

@Samirはとにかくbool名前が付けられintたPythonにはありません。
サンタ

ただし、ビットマスクの方が効率的であることに同意します(この「dict」の使い方によって異なります)。
サンタ

1
明確にするために、boolタイプは実際にはタイプのサブクラス(サブタイプ?)ですint
サンタ

回答:


64

見るとCソースのPython用dictの操作、あなたは彼らがかなりナイーブ(しかし、効率的な)コピーを行うことがわかります。基本的には、次の呼び出しに要約されますPyDict_Merge

PyDict_Merge(PyObject *a, PyObject *b, int override)

これは、それらが同じオブジェクトであるかどうか、オブジェクトが含まれているかどうかなどのクイックチェックを実行します。その後、ターゲット辞書に寛大な1回のサイズ変更/割り当てを行い、要素を1つずつコピーします。ビルトインよりも速くなるとは思いませんcopy()


1
dictsをまったく使用しないようにコードを書き直した方がいいようです。または、同じ処理を実行できるより高速なデータ構造を使用してください。答えてくれてありがとう!
Joern、2011年

56

あなたが言うように、どうやらdict.copyはより高速です。

[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = d.copy()"
1000000 loops, best of 3: 0.238 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = dict(d)"
1000000 loops, best of 3: 0.621 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "from copy import copy; d={1:1, 2:2, 3:3}" "new = copy(d)"
1000000 loops, best of 3: 1.58 usec per loop

比較してくれてありがとう!ほとんどの場所でdictコピーを使用しないようにコードを書き直そうとします。再度、感謝します!
Joern、2011年

4
毎回インポートを行うコストをカウントせずに最後の比較を行う方法は、timeit-s引数ですpython -m timeit -s "from copy import copy" "new = copy({1:1, 2:2, 3:3})"。あなたがそれにいる間、ディクテーションの作成も引き出します(すべての例について)
Thomas Wouters

ある特定のショットに多少の変動があるかもしれないので、多分プロセスを何度も繰り返すのが良いでしょう。
xiaohan2012 2014

2
Timeitはそれを行います。それが言うように、それは1000000回ループし、それを平均します。
utdemir 2014

タイミングが競合しています。a = {b:b for b in range(10000)} In [5]:%timeit copy(a)10000 loops、best of 3:186 µs per loop In [6]:%timeit deepcopy(a)100 loops、最高3:ループあたり14.1 ms In [7]:%timeit a.copy()1000ループ、最高3:ループあたり180 µs
Davoud Taghawi-Nejad

12

copy()をどのように使用しているかを確認できるように、コードサンプルを提供できますか?

あなたは使うことができます

new = dict(old)

しかし、私はそれが速くなるとは思わない。


5

これは古いスレッドだと思いますが、これは「dictコピーpython」の検索エンジンでの高い結果であり、「dictコピーパフォーマンス」の上位の結果です。これは関連性があると思います。

Python 3.7以降newDict = oldDict.copy()は、以前よりも最大5.5倍高速です。特に、現在のところ、newDict = dict(oldDict)このパフォーマンスの向上は見られません。

ここにもう少し情報があります


3

憶測に任せるものによっては、元の辞書をラップして、一種のコピーオンライトを実行することもできます。

「コピー」は、「キー」がまだ含まれていない場合、「親」ディクショナリで内容を検索するディクショナリですが、それ自体に変更が含まれています。

これは、オリジナルを変更することはなく、追加のルックアップによってコストが増えることはないと想定しています。


2

ただし、測定値は辞書のサイズによって異なります。10000エントリの場合、copy(d)とd.copy()はほとんど同じです。

a = {b: b for b in range(10000)} 
In [5]: %timeit copy(a)
10000 loops, best of 3: 186 µs per loop
In [6]: %timeit deepcopy(a)
100 loops, best of 3: 14.1 ms per loop
In [7]: %timeit a.copy()
1000 loops, best of 3: 180 µs per loop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.