एक अजगर शब्दकोश में मूल्यों पर मानचित्रण


243

एक शब्दकोश को देखते हुए { k1: v1, k2: v2 ... }मैं { k1: f(v1), k2: f(v2) ... }प्रदान करना चाहता हूं मैं एक समारोह पास करता हूं f

क्या कोई ऐसा फंक्शन है? या मुझे करना पड़ेगा

dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])

आदर्श रूप में मैं सिर्फ लिखूंगा

my_dictionary.map_values(f)

या

my_dictionary.mutate_values_with(f)

यदि मूल शब्दकोश उत्परिवर्तित है या प्रतिलिपि बनाई गई है, तो यह मेरे लिए कोई मायने नहीं रखता है।


2
अपने उदाहरण को लिखने का एक बेहतर तरीका होगा dict((k, f(v)) for k, v in mydict.iteritems()), यानी वर्ग कोष्ठक के बिना, जो एक जनरेटर के माध्यम से मध्यवर्ती सूची के निर्माण को रोक देगा।
बेरील

जवाबों:


354

ऐसा कोई समारोह नहीं है; ऐसा करने का सबसे आसान तरीका एक तानाशाही समझ का उपयोग करना है:

my_dictionary = {k: f(v) for k, v in my_dictionary.items()}

अजगर 2.7 में, मेमोरी को बचाने के .iteritems()बजाय विधि का उपयोग करें .items()। पाइथन 2.7 तक तानाशाह समझदार वाक्य रचना पेश नहीं की गई थी।

ध्यान दें कि सूचियों पर ऐसी कोई विधि नहीं है; आपको सूची समझ या map()फ़ंक्शन का उपयोग करना होगा ।

इस प्रकार, आप map()अपने तानाशाही के प्रसंस्करण के लिए फ़ंक्शन का उपयोग कर सकते हैं :

my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))

लेकिन यह वास्तव में पठनीय नहीं है।


5
+1: यह वही है जो मैं भी करूंगा। dict(zip(a, map(f, a.values())))मामूली रूप से छोटा है, लेकिन मुझे यह सोचना है कि यह क्या कर रहा है, और खुद को याद दिलाएं कि हां, अगर चाबियाँ बदलती नहीं हैं, तो उसी क्रम में कुंजियों और मूल्यों को पुनरावृत्त किया जाता है। मुझे बिल्कुल भी सोचने की ज़रूरत नहीं है कि तानाशाही क्या कर रही है, और इसलिए यह सही जवाब है।
DSM

2
@chiborg: ऐसा इसलिए है क्योंकि एक ही बार में सभी कुंजी-मूल्य जोड़े देखने के बजाय, आप अब नंबर-की-कुंजी बार my_dictionary.__getitem__कॉल का उपयोग कर रहे हैं ।
मार्टिन पीटर्स

1
ध्यान दें कि चूंकि PEP3113 (पायथन 3.x में लागू) टपल पैरामीटर अब समर्थित नहीं हैं: lambda (k,v): (k, f(v))कुछ इस तरह से फिर से लिखा जाना चाहिएlambda k_v: (k_v[0], f(k_v[1]))
normanius

1
पैरामीटर अनपैकिंग को निक्स्ड क्यों किया गया? वह सुधार कैसे है ?
जवादबा

3
एक एफपी भाषा से आने वाले, पायथन अविश्वसनीय रूप से अजीब लगेगा।
जुआनचेतो


21

आप इसे एक नया तानाशाही बनाने के बजाय एक जगह पर कर सकते हैं, जो बड़े शब्दकोशों के लिए बेहतर हो सकता है (यदि आपको प्रतिलिपि की आवश्यकता नहीं है)।

def mutate_dict(f,d):
    for k, v in d.iteritems():
        d[k] = f(v)

my_dictionary = {'a':1, 'b':2}
mutate_dict(lambda x: x+1, my_dictionary)

परिणाम में my_dictionary:

{'a': 2, 'b': 3}

1
कूल, आपको शायद यह नाम बदलने के mapdictलिए mutate_values_withया कुछ स्पष्ट करना चाहिए कि आप फिर से लिखेंगे! :)
टार्च

2
zip(d.keys(), d.values())इसके बजाय और संस्करणों के लिए काम करता हैiteritems()
ytpillai

1
@ytpillai 'ज़िप' या कॉम्प्रिहेंशन एक कॉपी बनाते हैं, न कि वैल्यूज़-प्लेस को बदलने के बजाय, जो मेरे उत्तर का उद्देश्य है। जब कोई प्रतिलिपि ठीक हो, तो स्वीकृत उत्तर सबसे अच्छा होता है।
gens

1
मेरी क्षमायाचना, मुझे महसूस नहीं हुआ कि आप आइटम विधि का उपयोग करना चाहते हैं। हालाँकि, इसके लिए एक और सुधार संभव है (गैर पायथन 2.7 उपयोगकर्ताओं के लिए){k:f(v) for k,v in iter(d.items())}
ytpillai

1
एक iterator बनाकर स्थान बचाता है
ytpillai

13

PEP-0469 के कारण जिसने पुनरावृत्तियाँ () को आइटमों () और PEP-3113 का नाम दिया है, जिन्होंने ट्यूपल पैरामीटर को अनपैकिंग से हटा दिया है , Python 3.x में आपको Martijn Pieters लिखना चाहिए like इसका उत्तर दें :

my_dictionary = dict(map(lambda item: (item[0], f(item[1])), my_dictionary.items()))

4

जबकि मेरे मूल उत्तर ने इस बिंदु को याद किया ( डिफ़ॉल्ट के कारखाने में एक्सेसिंग कुंजी के समाधान के साथ इस समस्या को हल करने की कोशिश करके ), मैंने वर्तमान प्रश्न के वास्तविक समाधान का प्रस्ताव करने के लिए इसे फिर से काम किया है।

यह रहा:

class walkableDict(dict):
  def walk(self, callback):
    try:
      for key in self:
        self[key] = callback(self[key])
    except TypeError:
      return False
    return True

उपयोग:

>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)

यह विचार है कि मूल तानाशाही को उप-वर्गित किया जाए ताकि इसे वांछित कार्यक्षमता दी जा सके: सभी मूल्यों पर एक फ़ंक्शन "मैपिंग"।

प्लस पॉइंट यह है कि इस शब्दकोश का उपयोग मूल डेटा को स्टोर करने के लिए किया जा सकता है जैसे कि यह dictएक कॉलबैक के साथ अनुरोध पर किसी भी डेटा को परिवर्तित करते समय किया गया था ।

बेशक, कक्षा और उस फ़ंक्शन को नाम देने के लिए स्वतंत्र महसूस करें जो आप चाहते हैं (इस उत्तर में चुना गया नाम PHP के array_walk()फ़ंक्शन से प्रेरित है )।

नोट: कार्यक्षमता के लिए न तो try- exceptब्लॉक और न ही returnकथन अनिवार्य हैं, वे PHP के व्यवहार को आगे बढ़ाने के लिए हैं array_walk


1
यह ओपी प्रश्न को हल करने में विफल रहता है क्योंकि __missing__मौजूदा कुंजियों के लिए विधि नहीं बुलाई जाएगी, जिसे हम बदलना चाहते हैं, जब तक कि फैक्ट्री विधि पास न हो जाए मूल का उपयोग किसी भी तरह कमबैक के रूप में करें, लेकिन जैसा कि उदाहरण के उपयोग का हिस्सा नहीं है, मैं इस समस्या पर एक असंतोषजनक उत्तर मानता हूं।
Kaos

कौन सी मौजूदा चाबियां?
7heo.tk

ओपी से Given a dictionary { k1: v1, k2: v2 ... } ...:। यही है, आप पहले से ही एक dictके साथ शुरू करने के लिए है ..
Kaos

मैं कहना चाहूंगा कि हम दोनों सही हैं; लेकिन मेरा मानना ​​है कि हम दोनों गलत हैं। आप सही हैं कि मेरा जवाब सवाल का जवाब नहीं है; लेकिन उस कारण के लिए नहीं जिसे आपने आमंत्रित किया था। मैंने बस इस बिंदु को याद किया, {v1: f(v1), v2: f(v2), ...}दिए गए तरीके को प्राप्त करने के लिए [v1, v2, ...], और एक तानाशाह को नहीं दिया। मैं सही करने के लिए अपने उत्तर को संपादित करूंगा।
7heo.tk

2

लैम्ब्डा के अंदर से अनुक्रमण करने से बचने के लिए, जैसे:

rval = dict(map(lambda kv : (kv[0], ' '.join(kv[1])), rval.iteritems()))

आप भी कर सकते हैं:

rval = dict(map(lambda(k,v) : (k, ' '.join(v)), rval.iteritems()))

यह दूसरे उदाहरण में 2-ट्यूपल के भीतर एक चालाक हेरफेर है। हालांकि, यह लैम्ब्डा के भीतर ऑटो ट्यूपल अनपैकिंग का उपयोग करता है, जो अब पायथन 3 में समर्थित नहीं है। इसलिए lambda(k,v)काम नहीं करेगा। देखें stackoverflow.com/questions/21892989/...
जोनाथन Komar

0

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

def mutate_dict_in_place(f, d):
    for k, v in d.iteritems():
        if isinstance(v, dict):
            mutate_dict_in_place(f, v)
        else:
            d[k] = f(v)

# Exemple handy usage
def utf8_everywhere(d):
    mutate_dict_in_place((
        lambda value:
            value.decode('utf-8')
            if isinstance(value, bytes)
            else value
        ),
        d
    )

my_dict = {'a': b'byte1', 'b': {'c': b'byte2', 'd': b'byte3'}}
utf8_everywhere(my_dict)
print(my_dict)

यह तब उपयोगी हो सकता है जब पाइथन 2 में बाइट्स के रूप में स्ट्रिंग्स को एन्कोड करने वाले json या yaml फाइलों से निपटते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.