पायथन में शब्दकोश कॉपी करने का तेज़ तरीका


92

मेरे पास एक पायथन कार्यक्रम है जो शब्दकोशों के साथ बहुत काम करता है। मुझे हजारों बार शब्दकोशों की प्रतियां बनानी होंगी। मुझे कुंजी और संबंधित सामग्री दोनों की एक प्रति चाहिए। प्रतिलिपि संपादित की जाएगी और इसे मूल से लिंक नहीं किया जाना चाहिए (जैसे प्रतिलिपि में परिवर्तन मूल को प्रभावित नहीं करना चाहिए।)

कीज़ स्ट्रिंग्स हैं, वैल्यूज़ इंटेगर (0/1) हैं।

मैं वर्तमान में एक सरल तरीके का उपयोग करता हूं:

newDict = oldDict.copy()

मेरा कोड प्रोफाइल करने से पता चलता है कि कॉपी ऑपरेशन में ज्यादातर समय लगता है।

वहाँ dict.copy()विधि के लिए तेजी से विकल्प हैं ? सबसे तेज क्या होगा?


1
यदि मान 0 या 1 हो सकता है, तो क्या a boolसे बेहतर विकल्प होगा int?
समीर तलवार

5
और अगर आपको उनमें से हजारों प्रतियों की आवश्यकता है, तो क्या बिटकॉइन बेहतर काम करेंगे?
Wooble

@ आमिर वैसे भी boolनामित पायथन में नहीं है int
सांता

मैं सहमत हूं, हालांकि, यह कि आपके लिए एक बिटमैस्क अधिक कुशल हो सकता है (यह निर्भर करता है कि आप इस "तानाशाह" का उपयोग कैसे करते हैं)।
सांता

1
स्पष्ट करने के लिए, boolप्रकार वास्तव में प्रकार का एक उपवर्ग (उपप्रकार?) है int
सांता 20

जवाबों:


64

को देखते हुए सी स्रोत अजगर के लिए dictसंचालन, जैसा कि आप देख सकते हैं कि वे एक बहुत भोली (लेकिन कुशल) प्रतिलिपि है। यह अनिवार्य रूप से एक कॉल करने के लिए नीचे फोड़े PyDict_Merge:

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

यह चीजों के लिए त्वरित जांच करता है जैसे कि वे एक ही वस्तु हैं और यदि उनमें वस्तुएं मिली हैं। उसके बाद यह एक उदारता करता है कि लक्ष्य तय करने के लिए एक बार आकार परिवर्तन / आवंटन किया जाता है और फिर तत्वों को एक-एक करके कॉपी किया जाता है। मैं आपको बिल्ट-इन की तुलना में बहुत तेज नहीं देख रहा हूं copy()


1
लगता है जैसे मैं बेहतर डायक्ट्स के उपयोग से बचने के लिए कोड को फिर से लिखता हूं - या एक तेज डेटा संरचना का उपयोग करता हूं जो एक ही काम कर सकता है। उत्तर के लिए बहुत बहुत धन्यवाद!
जोयर्न

56

जैसा कि आप कहते हैं, स्पष्ट रूप से तानाशाही तेज है।

[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

तुलना के लिए धन्यवाद! अधिकांश स्थानों पर तानाशाही नकल के उपयोग से बचने के लिए कोड को फिर से लिखने की कोशिश करेंगे। एक बार फिर धन्यवाद!
19

4
जिस तरह से आयात हर बार साथ है कर की लागत गिनती के बिना पिछले तुलना करने के लिए timeitके -sतर्क: python -m timeit -s "from copy import copy" "new = copy({1:1, 2:2, 3:3})"। जब आप उस पर हों, तो तानाशाही रचना को भी (सभी उदाहरणों के लिए) बाहर निकाल दें
थॉमस वाउटर्स

हो सकता है कि कई बार प्रक्रियाओं को दोहराएं बेहतर है क्योंकि एक विशिष्ट शॉट के कुछ उतार-चढ़ाव हो सकते हैं।
जिओहान २०२ २

2
समयसीमा ऐसा करती है; जैसा कि यह कहता है कि यह 1000000 बार लूप करता है और औसत है।
उदिमिर

मेरे पास परस्पर विरोधी समय है। a = {b: b for b in रेंज (10000)} में [5]:% समयसीति प्रतिलिपि (a) 10000 लूप, सर्वश्रेष्ठ 3: 186 Ins प्रति लूप में [6]:% timeit deepcopy (a) 100 लूप बेस्ट ऑफ़ 3: 14.1 एमएस प्रति लूप में [7]:% टाइमिट a.copy () 1000 लूप्स, बेस्ट ऑफ़ 3: 180 :s प्रति लूप
दाउद तगावी-नेजाद

12

क्या आप एक कोड नमूना प्रदान कर सकते हैं ताकि मैं देख सकूँ कि आप प्रतिलिपि () और किस संदर्भ में उपयोग कर रहे हैं?

आप उपयोग कर सकते हैं

new = dict(old)

लेकिन मुझे नहीं लगता कि यह तेजी से होगा।


5

मुझे लगता है कि यह एक पुराना धागा है, लेकिन यह "कमांड कॉपी पाइथन" के लिए खोज इंजन में एक उच्च परिणाम है, और "तानाशाही कॉपी प्रदर्शन" के लिए शीर्ष परिणाम है, और मेरा मानना ​​है कि यह प्रासंगिक है।

पायथन 3.7 से, newDict = oldDict.copy()यह पहले की तुलना में 5.5 गुना अधिक तेज है। विशेष रूप से, अभी newDict = dict(oldDict)इस प्रदर्शन में वृद्धि नहीं हुई है।

यहाँ थोड़ी और जानकारी है


3

अटकलें छोड़ने वाली चीजों के आधार पर, आप मूल शब्दकोश को लपेटना चाहते हैं और एक तरह की कॉपी-ऑन-राइट कर सकते हैं।

"प्रतिलिपि" तब एक शब्दकोश है जो "मूल" शब्दकोश में सामान दिखता है, अगर इसमें पहले से ही कुंजी नहीं है --- लेकिन अपने आप में संशोधन भर देता है।

यह मानता है कि आप मूल को संशोधित नहीं करेंगे और अतिरिक्त लुकअप अधिक लागत को समाप्त नहीं करेंगे।


2

हालाँकि, शब्दकोष आकार पर निर्भर होते हैं। 10000 प्रविष्टियों के लिए कॉपी (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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.