एक शब्दकोश कुंजी का नाम बदलें


400

क्या एक शब्दकोश कुंजी का नाम बदलने का एक तरीका है, एक नए नाम के लिए इसके मूल्य को फिर से असाइन किए बिना और पुराने नाम कुंजी को हटा देना; और तानाशाही कुंजी / मूल्य के माध्यम से पुनरावृत्ति के बिना?

ऑर्डरडीडिक्ट के मामले में, उस कुंजी की स्थिति को बनाए रखते हुए, वही करें।


7
वास्तव में "नए नाम पर इसके मान को पुनः दिए बिना और पुराने नाम की कुंजी को हटाए बिना" का क्या अर्थ है? जिस तरह से मैं इसे देखता हूं, वह एक कुंजी का नाम बदलने की परिभाषा है, और नीचे दिए गए सभी उत्तर मूल्य को पुन: असाइन करते हैं और पुराने कुंजी नाम को हटाते हैं। आपको अभी तक एक उत्तर स्वीकार करना बाकी है, इसलिए शायद ये पूरा नहीं हुआ है जो आप चाहते हैं?
18

5
आपको वास्तव में संस्करण संख्या निर्दिष्ट करने की आवश्यकता है। पायथन 3.7 के रूप में, भाषा की युक्ति अब गारंटी देती है कि डक्ट प्रविष्टि क्रम का पालन करते हैं । यह भी आदेशित आदेश को अधिकतर अप्रचलित बनाता है (जब तक कि) आप कोड चाहते हैं जो 2.x या 3.6- या बी के लिए भी बैकपार्ट करता है) क्या आप विल ऑर्डरेडड में सूचीबद्ध मुद्दों के बारे में परवाह करते हैं जो पायथन 3.7 में निरर्थक हो जाते हैं? )। और 3.6 में वापस, डिक्शनरी ऑर्डर की गारंटी सीपीथॉन कार्यान्वयन (लेकिन भाषा की कल्पना नहीं) द्वारा दी गई थी।
मार्सी

1
@smci पाइथन में 3.7 डायकशन इंसर्शन ऑर्डर का पालन करते हैं, हालांकि अभी भी इससे अलग हैं OrderedDict। dicts आदेश की अनदेखी करते हैं जब उनकी तुलना समानता के लिए की जा रही है, जबकि तुलना करते OrderedDictसमय आदेश को ध्यान में रखें। मुझे पता है कि आप कुछ ऐसा बताते हैं जो इसे समझाता है, लेकिन मुझे लगा कि आपकी टिप्पणी ने उन लोगों को गुमराह किया होगा जिन्होंने शायद उस लिंक को नहीं पढ़ा होगा।
फ्लिक डेम

@ फ़ीलम: यह सच है, लेकिन मैं यह नहीं देख सकता कि यह मायने रखता है, यह सवाल दो सवाल पूछता है, एक में, और दूसरे भाग के इरादे को छोड़ दिया गया। "जब वे समानता के लिए तुलना की जा रही हो तो आदेश की अवहेलना करते हैं" हाँ क्योंकि वे आदेश की तुलना करने वाले नहीं हैं। "OrderedDict ठीक है, जबकि तुलना में खाते में आदेश लेता है" ठीक है, लेकिन कोई भी पोस्ट 3.7 की परवाह नहीं करता है। मेरा दावा OrderedDictहै कि यह काफी हद तक अप्रचलित है, क्या आप इसकी वजह स्पष्ट नहीं कर सकते? उदाहरण के लिए यहाँ प्रेरक नहीं है जब तक आपको ज़रूरत न होreversed()
smci

@ फ़ीलम: मुझे कोई विश्वसनीय तर्क नहीं मिल रहा है कि ऑर्डरडाइक्ट 3.7+ में कोड पर अप्रचलित क्यों नहीं है, जब तक कि इसे प्री-3.7 या 2.x के साथ संगत नहीं होना है। तो जैसे यह सब प्रेरक नहीं है। विशेष रूप से "ऑर्डरड डिडक्ट का उपयोग करना आपके इरादे को बताता है ..." पूरी तरह से आवश्यक तकनीकी ऋण और मोटापे के लिए एक भयावह तर्क है। लोगों को बस वापस तानाशाही पर उतरना चाहिए और उस पर आगे बढ़ना चाहिए। यह सरल है।
smci

जवाबों:


712

एक नियमित तानाशाही के लिए, आप इसका उपयोग कर सकते हैं:

mydict[new_key] = mydict.pop(old_key)

एक आदेश के लिए, मुझे लगता है कि आपको एक समझ का उपयोग करके पूरी तरह से नया बनाना होगा।

>>> OrderedDict(zip('123', 'abc'))
OrderedDict([('1', 'a'), ('2', 'b'), ('3', 'c')])
>>> oldkey, newkey = '2', 'potato'
>>> OrderedDict((newkey if k == oldkey else k, v) for k, v in _.viewitems())
OrderedDict([('1', 'a'), ('potato', 'b'), ('3', 'c')])

कुंजी को स्वयं संशोधित करना, जैसा कि यह प्रश्न पूछ रहा है, अव्यवहारिक है क्योंकि सामान्य कुंजी आमतौर पर अपरिवर्तनीय वस्तुएं होती हैं जैसे संख्याएं, तार या टुपल्स। कुंजी को संशोधित करने की कोशिश करने के बजाय, एक नई कुंजी के लिए मूल्य को फिर से असाइन करना और पुरानी कुंजी को हटाना यह है कि आप अजगर में "नाम" कैसे प्राप्त कर सकते हैं।


अजगर 3.5 के लिए, मुझे लगता dict.popहै कि मेरे परीक्षण के आधार पर एक ऑर्डरडीड के लिए व्यावहारिक है।
डेनियल

5
नहीं, OrderedDictसम्मिलन आदेश को संरक्षित करेगा, जो वह नहीं है जिसके बारे में सवाल पूछा गया था।
विम

64

1 पंक्ति में सबसे अच्छी विधि:

>>> d = {'test':[0,1,2]}
>>> d['test2'] = d.pop('test')
>>> d
{'test2': [0, 1, 2]}

3
अगर आपके पास है तो d = {('test', 'foo'):[0,1,2]}क्या है
पेट्र फेडोसोव

4
@PetrFedosov, तो आप करते हैंd[('new', 'key')] = d.pop(('test', 'foo'))
रॉबर्ट सिएमर

17
यह उत्तर wim के उत्तर के दो साल बाद आया है जो सटीक वही बात बताता है, जिसमें कोई अतिरिक्त जानकारी नहीं है। मैं क्या खो रहा हूँ?
एंड्रास डीक

@AndrasDeak एक डिफरेंट के बीच का अंतर () और एक आर्डर डिडक्ट ()
Tcll

4
2013 से अपने शुरुआती संशोधन में wim का जवाब है , इसके बाद से ही कुछ बदलाव हुए हैं । क्रम केवल ओपी की कसौटी से आता है।
डीक

29

newkey!=oldkeyइस तरह से एक चेक का उपयोग करना , आप कर सकते हैं:

if newkey!=oldkey:  
    dictionary[newkey] = dictionary[oldkey]
    del dictionary[oldkey]

4
यह खूबसूरती से काम करता है, लेकिन मूल क्रम को बनाए नहीं रखता है क्योंकि नई कुंजी डिफ़ॉल्ट रूप से (python3 में) मिलती है।
szeitlin

2
यदि आप dictpython3.6 + इसे ऑर्डर किए गए फॉर्म में दर्ज करते हैं, तो पिछले संस्करणों पर निर्भर नहीं करता है और यह वास्तव में कैसे py3.6 + dicts बदल रहे थे की सिर्फ एक विशेषता के बाद की सुविधा नहीं है। OrderedDictयदि आप आदेश की परवाह करते हैं तो उपयोग करें ।
ग्रैनिटोसॉरस

2
धन्यवाद @Granitosaurus, मुझे आपको यह समझाने की आवश्यकता नहीं थी कि। वह मेरी टिप्पणी की बात नहीं थी।
स्वेज़लीन

5
@szeitlin ने आपकी टिप्पणी में निहित किया कि यह तथ्य कि यह किसी तरह से आकार या रूप में तानाशाही व्यवस्था के मामलों को बदल देता है, जब वास्तविकता में किसी को भी शब्दकोश के आदेश पर भरोसा नहीं करना चाहिए, तो यह तथ्य पूरी तरह से अप्रासंगिक है
ग्रैनिटोसॉरस

11

सभी शब्दकोश कुंजियों का नाम बदलने के मामले में:

target_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
new_keys = ['k4','k5','k6']

for key,n_key in zip(target_dict.keys(), new_keys):
    target_dict[n_key] = target_dict.pop(key)

1
क्या target_dict.keys()गारंटी के समान ही परिभाषा है? मैंने सोचा कि एक पायथन
तानाशाह अनियंत्रित है

मुझे लगता है कि आपको कुछ बिंदुओं पर अपनी चाबियों को
छांटना

10

आप OrderedDict recipeरेमंड हेटिंगर द्वारा लिखित इस का उपयोग कर सकते हैं और इसे एक renameविधि जोड़ने के लिए संशोधित कर सकते हैं , लेकिन यह जटिलता में एक ओ (एन) होने जा रहा है:

def rename(self,key,new_key):
    ind = self._keys.index(key)  #get the index of old key, O(N) operation
    self._keys[ind] = new_key    #replace old key with new key in self._keys
    self[new_key] = self[key]    #add the new key, this is added at the end of self._keys
    self._keys.pop(-1)           #pop the last item in self._keys

उदाहरण:

dic = OrderedDict((("a",1),("b",2),("c",3)))
print dic
dic.rename("a","foo")
dic.rename("b","bar")
dic["d"] = 5
dic.rename("d","spam")
for k,v in  dic.items():
    print k,v

उत्पादन:

OrderedDict({'a': 1, 'b': 2, 'c': 3})
foo 1
bar 2
c 3
spam 5

1
@Merose अपने मॉड्यूल खोज पथ में कहीं पायथन फ़ाइल जोड़ें और उससे आयात करें OrderedDict। लेकिन मैं सिफारिश करूंगा: एक ऐसा वर्ग बनाएं जो विरासत में मिले OrderedDictऔर उसमें एक renameविधि जोड़ें ।
अश्विनी चौधरी

ऑर्डरड डिक्ट जैसे लगता है कि एक डबल-लिंक की गई सूची का उपयोग करने के लिए फिर से लिखा गया है, इसलिए शायद अभी भी ऐसा करने का एक तरीका है, लेकिन इसके लिए बहुत अधिक कलाबाजी की आवश्यकता है। : - /
szeitlin

6

मुझसे पहले कुछ लोगों ने .popएक लाइनर में एक कुंजी को हटाने और बनाने की चाल का उल्लेख किया था ।

मुझे व्यक्तिगत रूप से अधिक स्पष्ट कार्यान्वयन अधिक पठनीय लगता है:

d = {'a': 1, 'b': 2}
v = d['b']
del d['b']
d['c'] = v

रिटर्न के ऊपर कोड {'a': 1, 'c': 2}


1

अन्य उत्तर बहुत अच्छे हैं। लेकिन python3.6 में, नियमित रूप से हुक्म का भी आदेश है। इसलिए सामान्य स्थिति में कुंजी की स्थिति बनाए रखना कठिन है।

def rename(old_dict,old_name,new_name):
    new_dict = {}
    for key,value in zip(old_dict.keys(),old_dict.values()):
        new_key = key if key != old_name else new_name
        new_dict[new_key] = old_dict[key]
    return new_dict

1

पायथन में 3.6 (बाद में?) मैं निम्नलिखित एक-लाइनर के लिए जाऊंगा

test = {'a': 1, 'old': 2, 'c': 3}
old_k = 'old'
new_k = 'new'
new_v = 4  # optional

print(dict((new_k, new_v) if k == old_k else (k, v) for k, v in test.items()))

जो पैदा करता है

{'a': 1, 'new': 4, 'c': 3}

यह ध्यान देने योग्य है कि printबयान के बिना ipython कंसोल / ज्यूपिटर नोटबुक अपने चुनने के क्रम में शब्दकोश प्रस्तुत करता है ...


0

मैं इस फ़ंक्शन के साथ आया था जो मूल शब्दकोश को म्यूट नहीं करता है। यह फ़ंक्शन शब्दकोशों की सूची का भी समर्थन करता है।

import functools
from typing import Union, Dict, List


def rename_dict_keys(
    data: Union[Dict, List[Dict]], old_key: str, new_key: str
):
    """
    This function renames dictionary keys

    :param data:
    :param old_key:
    :param new_key:
    :return: Union[Dict, List[Dict]]
    """
    if isinstance(data, dict):
        res = {k: v for k, v in data.items() if k != old_key}
        try:
            res[new_key] = data[old_key]
        except KeyError:
            raise KeyError(
                "cannot rename key as old key '%s' is not present in data"
                % old_key
            )
        return res
    elif isinstance(data, list):
        return list(
            map(
                functools.partial(
                    rename_dict_keys, old_key=old_key, new_key=new_key
                ),
                data,
            )
        )
    raise ValueError("expected type List[Dict] or Dict got '%s' for data" % type(data))

-1

मैं @wim के उत्तर का उपयोग कर रहा हूँ, तानाशाही के साथ। () कुंजियों का नाम बदलने के दौरान, लेकिन मुझे एक गोत्र मिला। कुंजी को बदलने के लिए तानाशाही के माध्यम से साइकिल चलाना, पुरानी कुंजियों की सूची को पूरी तरह से तानाशाही से अलग किए बिना, जिसके परिणामस्वरूप साइकिल चलाना नया, बदल गई कुंजी को लूप में बदल दिया गया और कुछ मौजूदा चाबियाँ गायब हो गईं।

शुरुआत करने के लिए, मैंने इसे इस तरह किया:

for current_key in my_dict:
    new_key = current_key.replace(':','_')
    fixed_metadata[new_key] = fixed_metadata.pop(current_key)

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

मैं अब यह कर रहा हूँ:

current_keys = list(my_dict.keys())
for current_key in current_keys:
    and so on...

बदलते हुक्म के सन्दर्भ से मुक्त होने के लिए my_dict.keys () को एक सूची में बदलना आवश्यक था। सिर्फ my_dict.keys () का उपयोग करके मुझे अजीब उदाहरणों के साथ मूल उदाहरण से बांधे रखा गया।


-1

यदि कोई व्यक्ति नए नामों के साथ सूची प्रदान करते समय सभी कुंजियों का नाम बदलना चाहता है:

def rename_keys(dict_, new_keys):
    """
     new_keys: type List(), must match length of dict_
    """

    # dict_ = {oldK: value}
    # d1={oldK:newK,} maps old keys to the new ones:  
    d1 = dict( zip( list(dict_.keys()), new_keys) )

          # d1{oldK} == new_key 
    return {d1[oldK]: value for oldK, value in dict_.items()}

-1

@ helloswift123 मुझे आपका कार्य पसंद है। यहां एकल कॉल में कई कुंजियों का नाम बदलने का एक संशोधन है:

def rename(d, keymap):
    """
    :param d: old dict
    :type d: dict
    :param keymap: [{:keys from-keys :values to-keys} keymap]
    :returns: new dict
    :rtype: dict
    """
    new_dict = {}
    for key, value in zip(d.keys(), d.values()):
        new_key = keymap.get(key, key)
        new_dict[new_key] = d[key]
    return new_dict

-2

मान लीजिए कि आप कुंजी k3 से k4 का नाम बदलना चाहते हैं:

temp_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
temp_dict['k4']= temp_dict.pop('k3')

1
काम नहीं करता, क्या आपका मतलब था ... temp_dict ['k4'] = temp_dict.pop ('k3')?
डगआर

यह एक वापस आ जाएगी TypeError: 'dict' object is not callableसाथ अगर temp_dict('k3')आप का मान संदर्भित करने के लिए कोशिश कर रहे हैं k3कुंजी तो आप वर्ग कोष्ठक और नहीं कोष्ठक का उपयोग करना चाहिए। हालाँकि, यह केवल शब्दकोश में एक नई कुंजी जोड़ देगा और अनुरोध के अनुसार एक मौजूदा कुंजी का नाम नहीं बदलेगा।
जैस्मिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.