दो सूचियों को शब्दकोश में परिवर्तित करें


1226

कल्पना कीजिए कि आपके पास:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

निम्नलिखित शब्दकोश का निर्माण करने का सबसे सरल तरीका क्या है?

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

जवाबों:


2140

ऐशे ही:

>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}

Voila :-) जोड़ीदार dictकंस्ट्रक्टर और zipफ़ंक्शन बहुत उपयोगी हैं: https://docs.python.org/3/library/functions.html#func-dict


3
यह ध्यान देने योग्य है कि dictionary = {zip(keys, values)}काम नहीं करेगा। आपको स्पष्ट रूप से घोषित करना होगाdict(...)
फर्नांडो विटमैन

5
यकीन नहीं होता कि आप इसे @FernandoWittmann से क्यों उम्मीद करेंगे। {thing}एक set()युक्त एक तत्व का निर्माण करने के लिए वाक्य रचना चीनी है । {*iterable}एक setयुक्त कई तत्वों का निर्माण करने के लिए वाक्य रचना चीनी है । {k:v}या एक निर्माण {**mapping} करेगाdict , लेकिन यह वाक्यात्मक रूप से काफी अलग है।
डैन लेन्स्की

6
टिप्पणी के लिए धन्यवाद Dan। तुम सही हो। मेरा भ्रम इसलिए हुआ क्योंकि मैं आमतौर पर {}शब्दकोशों के लिए सिंटेक्स का उपयोग करता हूं । वास्तव में, यदि हम प्रयास करें type({})कि आउटपुट है dict। लेकिन वास्तव में, अगर हम कोशिश करें type({thing})तो आउटपुट है set
फर्नांडो विटमैन

मैं इस मामले में यहां आया हूं कि हम इससे बेहतर कर सकते हैं {k:v for k, v in zip(keys, values)}। यह पता चलता है कि हम कर सकते हैं। +1।
जेजी

139

कल्पना कीजिए कि आपके पास:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

निम्नलिखित शब्दकोश का निर्माण करने का सबसे सरल तरीका क्या है?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

अधिकांश कलाकार, dictनिर्माता के साथzip

new_dict = dict(zip(keys, values))

पायथन 3 में, ज़िप अब एक आलसी इटरेटर लौटाता है, और यह अब सबसे अच्छा प्रदर्शन है।

dict(zip(keys, values))प्रत्येक के लिए एक बार वैश्विक लुकअप की आवश्यकता होती है dictऔरzip , लेकिन यह किसी भी अनावश्यक मध्यवर्ती डेटा-संरचनाओं का निर्माण नहीं करता है या फ़ंक्शन अनुप्रयोग में स्थानीय लुकअप से निपटना पड़ता है।

रनर-अप, तानाशाही समझ:

तानाशाह कंस्ट्रक्टर का उपयोग करने के लिए एक करीबी उपविजेता एक तानाशाह समझ के मूल वाक्यविन्यास का उपयोग करना है (एक सूची समझ नहीं है , जैसा कि दूसरों ने गलती से डाल दिया है):

new_dict = {k: v for k, v in zip(keys, values)}

इसे तब चुनें जब आपको चाबी या मूल्य के आधार पर मैप या फ़िल्टर करने की आवश्यकता हो।

पायथन 2 में, zipएक सूची देता है, एक अनावश्यक सूची बनाने से बचने के लिए, izipइसके बजाय का उपयोग करें (सचेतक ज़िप के लिए जब आप पायथन 3 में जाते हैं तो कोड परिवर्तन कम कर सकते हैं)।

from itertools import izip as zip

तो यह अभी भी (2.7) है:

new_dict = {k: v for k, v in zip(keys, values)}

अजगर 2, <= 2.6 के लिए आदर्श

izipसे itertoolsहो जाता है zipपायथन 3. में izipअजगर 2 के लिए ज़िप की तुलना में बेहतर है, और 2.6 या नीचे के लिए आदर्श (क्योंकि यह अनावश्यक सूची निर्माण से बचा जाता है):

from itertools import izip
new_dict = dict(izip(keys, values))

सभी मामलों के लिए परिणाम:

सभी मामलों में:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

स्पष्टीकरण:

यदि हम मदद को dictदेखते हैं तो हम देखते हैं कि यह तर्कों के विभिन्न रूपों को लेता है:


>>> help(dict)

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)

अनावश्यक डेटा संरचनाओं को बनाने से परहेज करते हुए इष्टतम दृष्टिकोण एक पुनरावृत्ति का उपयोग करना है। पायथन 2 में, ज़िप एक अनावश्यक सूची बनाता है:

>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

पायथन 3 में, समकक्ष होगा:

>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

और पायथन 3 zipकेवल एक चलने योग्य वस्तु बनाता है:

>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>

चूँकि हम अनावश्यक डेटा स्ट्रक्चर्स बनाने से बचना चाहते हैं, हम आमतौर पर पाइथन 2 से बचना चाहते हैं zip(क्योंकि यह एक अनावश्यक लिस्ट बनाता है)।

कम प्रदर्शन करने वाले विकल्प:

यह एक रचनात्मक अभिव्यक्ति है जो तानाशाह को दी जाती है:

generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)

या समकक्ष:

dict((k, v) for k, v in zip(keys, values))

और यह एक सूची है जिसे तानाशाह को पारित किया जा रहा है:

dict([(k, v) for k, v in zip(keys, values)])

पहले दो मामलों में, गैर-ऑपरेटिव (इस प्रकार अनावश्यक) संगणना की एक अतिरिक्त परत ज़िप के चलने योग्य पर रखी जाती है, और सूची की समझ के मामले में, एक अतिरिक्त सूची अनावश्यक रूप से बनाई जाती है। मैं उन सभी से कम प्रदर्शन करने की उम्मीद करूंगा, और निश्चित रूप से अधिक नहीं।

प्रदर्शन मूल्यांकन:

उबंटू 16.04 पर निक्स द्वारा प्रदान किए गए 64 बिट पायथन 3.8.2 में, सबसे तेज से सबसे धीमी गति से ऑर्डर किया गया:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>> 
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583

dict(zip(keys, values)) कुंजियों और मूल्यों के छोटे सेटों के साथ भी जीतता है, लेकिन बड़े सेटों के लिए, प्रदर्शन में अंतर अधिक हो जाएगा।

एक टिप्पणीकार ने कहा:

minप्रदर्शन की तुलना करने का एक बुरा तरीका लगता है। निश्चित रूप से meanऔर / या maxवास्तविक उपयोग के लिए बहुत अधिक उपयोगी संकेतक होंगे।

हम उपयोग करते हैं minक्योंकि ये एल्गोरिदम नियतात्मक हैं। हम सर्वोत्तम संभव परिस्थितियों में एल्गोरिदम के प्रदर्शन को जानना चाहते हैं।

यदि ऑपरेटिंग सिस्टम किसी भी कारण से लटका हुआ है, तो इसका कोई लेना देना नहीं है कि हम क्या तुलना करने की कोशिश कर रहे हैं, इसलिए हमें अपने विश्लेषण से उन प्रकार के परिणामों को बाहर करने की आवश्यकता है।

यदि हम उपयोग करते हैं mean, तो उन प्रकार की घटनाओं से हमारे परिणाम बहुत कम हो जाएंगे, और यदि हम उपयोग maxकरते हैं तो हमें केवल सबसे चरम परिणाम मिलेगा - ऐसी घटना से सबसे अधिक प्रभावित होने की संभावना है।

एक टिप्पणीकार भी कहता है:

मीन 3.6.8 में, मीन मूल्यों का उपयोग करते हुए, इन छोटी सूचियों के लिए लगभग 30% तक तानाशाह की समझ वास्तव में अभी भी तेज है। बड़ी सूचियों (10k यादृच्छिक संख्या) के लिए, dictकॉल लगभग 10% तेज है।

मुझे लगता है हम dict(zip(...10k यादृच्छिक संख्या के साथ मतलब है । यह काफी असामान्य उपयोग के मामले की तरह लगता है। यह समझ में आता है कि बड़े डेटासेट में सबसे प्रत्यक्ष कॉल हावी होगी, और मुझे आश्चर्य नहीं होगा यदि ओएस हैंग दे रहा है, तो उस परीक्षण को चलाने में कितना समय लगेगा, आगे आपके नंबरों को तिरछा करना होगा। और अगर आप उपयोग करते हैं meanयाmax मैं आपके परिणामों को अर्थहीन मानूंगा।

आइए हमारे शीर्ष उदाहरणों पर अधिक यथार्थवादी आकार का उपयोग करें:

import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))

और हम यहां देखते हैं कि dict(zip(...वास्तव में बड़े डेटासेट के लिए लगभग 20% तेजी से चलता है।

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095

1
2019 के मध्य (अजगर 3.7.3) के अनुसार, मुझे अलग समय मिल रहा है। %% समयसीमा 1.57 \ pm 0.019microsec के लिए dict(zip(headList, textList))और 1.95 \ pm 0.030 microsec के लिए देता है {k: v for k, v in zip(headList, textList)}। मैं पूर्व में पठनीयता और गति के लिए सुझाव दूंगा। जाहिर है यह मिनट () बनाम माध्य () समयसीमा के लिए तर्क पर मिलता है।
मार्क_ एंडरसन

1
minप्रदर्शन की तुलना करने का एक बुरा तरीका लगता है। निश्चित रूप से meanऔर / या maxवास्तविक उपयोग के लिए बहुत अधिक उपयोगी संकेतक होंगे।
n

1
मीन 3.6.8 में, मीन मूल्यों का उपयोग करते हुए, इन छोटी सूचियों के लिए लगभग 30% तक तानाशाह की समझ वास्तव में अभी भी तेज है। बड़ी सूचियों (10k यादृच्छिक संख्या) के लिए, dictकॉल लगभग 10% तेज है।
n

@ n-0101 - मैंने अपने जवाब में आपकी टिप्पणियों को संबोधित किया।
हारून हॉल

3
10k नंबर सिर्फ एक त्वरित तरीका था जिससे 2 अद्वितीय तत्वों की लंबी सूची तैयार की गई। सूची पीढ़ी समय अनुमान के बाहर की गई थी। / / आपको क्यों लगता है कि औसत या अधिकतम बेकार हैं? यदि आप ऐसा कई बार कर रहे हैं, तो आपका औसत समय ~ n * माध्य है, और ऊपरी सीमा ~ n * अधिकतम है। आपका न्यूनतम एक कम बाउंड प्रदान करता है, लेकिन ज्यादातर लोग औसत या सबसे खराब स्थिति वाले प्रदर्शन की परवाह करते हैं। यदि उच्च विचरण होता है, तो आपका न्यूनतम अधिकांश मामलों में पूरी तरह से अप्रकाशित होगा। वास्तविक दुनिया के परिदृश्य में न्यूनतम अधिक सार्थक कैसे है?
n

128

इसे इस्तेमाल करे:

>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}

पायथन 2 में, इसकी तुलना में मेमोरी खपत में अधिक किफायती है zip


18
पायथन 2 के लिए सच है, लेकिन पायथन 3 में, zipपहले से ही मेमोरी खपत में किफायती है। docs.python.org/3/library/functions.html#zip वास्तव में, आप देख सकते हैं कि पायथन 3 में sixउपयोग करता zipहै itertools.izipजो पायथन 2 pythonhosted.org/six को बदलने के लिए है ।
पेड्रो कटोरी

35
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}

28

आप पायथन ≥ 2.7 में शब्दकोश समझ का उपयोग भी कर सकते हैं:

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}

17

शब्दकोश की समझ का उपयोग करने के लिए एक अधिक प्राकृतिक तरीका है

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}

कभी-कभी यह सबसे तेज़ तरीका है और कभी-कभी यह dictऑब्जेक्ट में बदलने के लिए सबसे धीमा है , ऐसा क्यों है ?, धन्यवाद दोस्त।
हरितसिंह गोहिल

13

यदि आपको शब्दकोश बनाने से पहले कुंजियों या मूल्यों को बदलने की आवश्यकता है तो एक जनरेटर अभिव्यक्ति का उपयोग किया जा सकता है। उदाहरण:

>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3])) 

एक नज़र लो कोड लाइक ए पाइथोनिस्टा: आइडोमैटिक पायथन


10

पायथन 3.x के साथ, तानाशाह की समझ के लिए जाता है

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in zip(keys, values)}

print(dic)

यहाँ पर व्यापक समझ पर , एक उदाहरण है:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

8

उन लोगों के लिए जिन्हें सरल कोड की आवश्यकता है और वे परिचित नहीं हैं zip:

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

यह कोड की एक पंक्ति द्वारा किया जा सकता है:

d = {List1[n]: List2[n] for n in range(len(List1))}

6
जोर से विफल रहता है List1से अधिक लंबी हैList2
जीन फ़्राँस्वा Fabre

@ जीन-फ्रांस्वा फाबरे क्या यह वास्तव में मायने रखता है? क्या कारण है कि हमें शब्दकोश बनाने के लिए अलग-अलग लंबाई वाली दो सूचियों को weive करना चाहिए?
प्यार किया। येशुस

शायद नहीं, लेकिन उसके बाद यह for n in range(len(List1))एक विरोधी पैटर्न है
जीन फ़्राँस्वा Fabre

3
  • 2018/04/18

सबसे अच्छा समाधान अभी भी है:

In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...: 

In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}

इसे बदल दें:

    lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
    keys, values = zip(*lst)
    In [101]: keys
    Out[101]: ('name', 'age', 'food')
    In [102]: values
    Out[102]: ('Monty', 42, 'spam')

2

आप इसे नीचे दिए गए कोड का उपयोग कर सकते हैं:

dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))

लेकिन सुनिश्चित करें कि सूचियों की लंबाई समान होगी। यदि लंबाई समान नहीं होती है। तो जिप फ़ंक्शन लंबे समय तक चालू रहता है।


2

मुझे यह संदेह था जब मैं एक ग्राफ से संबंधित समस्या को हल करने की कोशिश कर रहा था। मेरे पास जो मुद्दा था, मुझे एक खाली आसन्न सूची को परिभाषित करने की आवश्यकता थी और एक रिक्त सूची के साथ सभी नोड्स को इनिशियलाइज़ करना चाहता था, कि जब मैंने सोचा कि मैं कैसे जांचूँ कि यह काफी तेज़ है, तो मेरा मतलब है कि यह ज़िप ऑपरेशन करने के लायक होगा। साधारण असाइनमेंट की-वैल्यू जोड़ी के बजाय। ज्यादातर समय के बाद, समय कारक एक महत्वपूर्ण बर्फ तोड़ने वाला है। इसलिए मैंने दोनों तरीकों के लिए टाइमिट ऑपरेशन किया।

import timeit
def dictionary_creation(n_nodes):
    dummy_dict = dict()
    for node in range(n_nodes):
        dummy_dict[node] = []
    return dummy_dict


def dictionary_creation_1(n_nodes):
    keys = list(range(n_nodes))
    values = [[] for i in range(n_nodes)]
    graph = dict(zip(keys, values))
    return graph


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped

iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)

for trail in range(1, 8):
    print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')

N_nodes = 10,000,000 के लिए मुझे मिलता है,

Iteration: 2.825081646999024 शॉर्टहैंड: 3.535717916001886

Iteration: 5.051560923002398 शॉर्टहैंड: 6.255070794999483

Iteration: 6.52859034499852 शॉर्टहैंड: 8.221581164998497

Iteration: 8.683652416999394 शॉर्टहैंड: 12.599181543999293

Iteration: 11.587241565001023 शॉर्टहैंड: 15.27298851100204

Iteration: 14.816342867001367 शॉर्टहैंड: 17.162912737003353

Iteration: 16.645022411001264 शॉर्टहैंड: 19.976680120998935

आप एक निश्चित बिंदु के बाद स्पष्ट रूप से देख सकते हैं, n_th चरण पर पुनरावृत्ति दृष्टिकोण n-1_th चरण में आशुलिपि दृष्टिकोण द्वारा उठाए गए समय से आगे निकल जाता है।


1

यहाँ आप को डिक्शनरी में सूची मूल्य जोड़ने का एक उदाहरण दिया गया है

list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)

हमेशा सुनिश्चित करें कि आपका "कुंजी" (सूची 1) हमेशा पहले पैरामीटर में है।

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}

0

विलुप्त होने के साथ शब्दकोश समझ के रूप में समाधान:

dict = {item : values[index] for index, item in enumerate(keys)}

एन्युमरेट के साथ लूप के लिए समाधान:

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]

0

आप एक सूची के साथ भी कोशिश कर सकते हैं जो दो सूचियों का संयोजन है;)

a = [1,2,3,4]
n = [5,6,7,8]

x = []
for i in a,n:
    x.append(i)

print(dict(zip(x[0], x[1])))

-1

विधि ज़िप समारोह के बिना

l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
    for l2_ in l2:
        d1[l1_] = l2_
        l2.remove(l2_)
        break  

print (d1)


{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}

हाय xiyurui, इनपुट (l1 और l2) एक सूची होनी चाहिए। यदि आप एक सेट के रूप में l1 और l2 असाइन करते हैं तो यह प्रविष्टि क्रम को संरक्षित नहीं कर सकता है। मेरे लिए मुझे {1: 'a', 2: 'c', 3: 'd', 4: 'b', 5: 'e'} के रूप में
आउटपुट मिला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.