অভিধানের কী নামকরণ করুন


400

কোনও অভিধান কীটির নতুন নাম পরিবর্তন করে এবং পুরানো নাম কীটি সরিয়ে না দিয়ে কি নামকরণের কোনও উপায় আছে; এবং ডিক কী / মান দিয়ে পুনরাবৃত্তি না করে?

অর্ডারডিক্টের ক্ষেত্রে, কীটির অবস্থানটি ধরে রেখে একই কাজ করুন।


7
"নতুন নামের সাথে এর মানটি পুনরায় স্থাপন না করে এবং পুরাতন নাম কীটি অপসারণ না করে" এর অর্থ কী? আমি এটি যেভাবে দেখছি, এটি একটি কী নামকরণের সংজ্ঞা এবং নীচের সমস্ত উত্তরগুলি পুনরায় মূল্য নির্ধারণ করে এবং পুরানো কী নামটি সরিয়ে দেয়। আপনি এখনও একটি উত্তর গ্রহণ করতে পারেন, তাই সম্ভবত এইগুলি আপনি যা সন্ধান করছেন তা অর্জন করেন নি?
dbliss

5
আপনার সত্যিই সংস্করণ নম্বর (গুলি) নির্দিষ্ট করা দরকার। পাইথন ৩.7 অনুসারে, ভাষা স্পেসটি এখন গ্যারান্টি দেয় যে ডিক্টগুলি সন্নিবেশ ক্রম অনুসরণ করে । এটি অর্ডারডিক্টকে বেশিরভাগই অপ্রচলিত করে তোলে (যদি না আপনি) কোডটি চান যা 2.x বা 3.6- তেও ব্যাকপোর্ট করে বা খ) আপনি উইল অর্ডারডিক্টে তালিকাভুক্ত সমস্যাগুলি পাইথন ৩.7 এ অপ্রয়োজনীয় হয়ে উঠবেন? )। এবং ফিরে back. back-তে, অভিধান সন্নিবেশ আদেশটি সিপিথন বাস্তবায়ন দ্বারা গ্যারান্টিযুক্ত ছিল (তবে ভাষাটি নয়)।
স্মি

1
@ এসএমসি পাইথনে ৩.7 ডিক্ট সন্নিবেশ ক্রম অনুসরণ করে, তবে এখনও এর থেকে আলাদা রয়েছে OrderedDict। ডিক্টস সাম্যের জন্য তুলনা করা হচ্ছে যখন আদেশটিকে অগ্রাহ্য করে, অন্যদিকে তুলনা OrderedDictকরার সময় অ্যাকাউন্টটিকে বিবেচনা করে account আমি জানি আপনি এমন কোনও লিঙ্কের সাথে লিঙ্ক করেছেন যা এটি ব্যাখ্যা করে তবে আমি ভেবেছিলাম আপনার মন্তব্য সম্ভবত তাদের যারা বিভ্রান্ত করেছে তারা এই লিঙ্কটি পড়ে না।
ফ্লিম

@ ফ্লিম: এটি সত্য তবে আমি দেখতে পাচ্ছি না যে এটি গুরুত্বপূর্ণ, এই প্রশ্নটি দুটি প্রশ্ন জিজ্ঞাসা করে, এবং দ্বিতীয় অংশের উদ্দেশ্যকে ছাড় দেওয়া হয়েছিল। "সামঞ্জস্যের তুলনায় তুলনামূলকভাবে ডিক্টরা অর্ডার উপেক্ষা করে" হ্যাঁ কারণ তারা আদেশ অনুসারে তুলনা করার কথা নয়। " OrderedDictযখন তুলনা করা হচ্ছে তখন অর্ডারটিকে বিবেচনায় নিয়েছে" ঠিক আছে তবে নুনি -3.7 পরবর্তী পোস্ট করে না। আমি দাবি করি যে OrderedDictএটি মূলত অপ্রচলিত, আপনি কেন এটির কারণগুলি ব্যাখ্যা করতে পারেন? যেমন আপনার প্রয়োজন না হলে এখানে অনুপ্রেরণাকারী নয়reversed()
smci

@ ফ্লিম: অর্ডারডিক্ট কেন 3.7+ এ কোডে অপ্রচলিত নয় এমন কোনও বিশ্বাসযোগ্য যুক্তি খুঁজে পাচ্ছি না যতক্ষণ না এটি প্রাক-3.7 বা 2.x এর সাথে সামঞ্জস্য হতে হয় unless যেমন সুতরাং এই সব প্ররোচনামূলক হয় না। বিশেষত "অর্ডারডটিক্ট ব্যবহার করা আপনার অভিপ্রায়টি যোগাযোগ করে ..." সম্পূর্ণ প্রয়োজনীয় প্রযুক্তিগত debt ণ এবং অবনতির জন্য একটি ভীতিকর যুক্তি। লোকেরা কেবল ডিকটিতে ফিরে যেতে হবে এবং এটির সাথে চালিয়ে যাওয়া উচিত। এটা সহজ.
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সন্নিবেশ ক্রম সংরক্ষণ করবে, যা প্রশ্নটি জিজ্ঞাসা করেছিল তা নয়।
wim

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
@ পেটারফেদোসোভ, তারপরে আপনি করুনd[('new', 'key')] = d.pop(('test', 'foo'))
রবার্ট সিমার

17
এই উত্তরটি উইমের উত্তর দেওয়ার দু'বছর পরে এসেছিল যা কোনও অতিরিক্ত তথ্য ছাড়াই ঠিক একই জিনিসটি বোঝায়। আমি কী মিস করছি?
আন্দ্রেস ডেক

@ আন্দ্রেসডিক একটি ডিক () এবং অর্ডারডিক্ট () এর মধ্যে পার্থক্য
Tcll

4
২০১৩ সাল থেকে তার প্রাথমিক পুনর্বিবেচনায় উইমের উত্তর , এর পরে কেবলমাত্র সংযোজন রয়েছে। অর্ডারনেসটি কেবল ওপির মানদণ্ড থেকে আসে।
আন্দ্রেস ডেক

29

এর জন্য একটি চেক ব্যবহার করে newkey!=oldkeyআপনি এইভাবে করতে পারেন:

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

4
এটি সুন্দরভাবে কাজ করে, তবে মূল ক্রমটি বজায় রাখে না কারণ নতুন কীটি ডিফল্টরূপে শেষে যুক্ত হয় (পাইথন 3 এ)।
szeitlin

2
@ সিজেটলিনে আপনাকে dictঅর্ডারের উপর নির্ভর করা উচিত নয় , যদিও পাইথন ৩. + + অর্ডারযুক্ত আকারে এটি অন্তর্নিহিত করে, পূর্ববর্তী সংস্করণগুলি দেয় না এবং এটি কীভাবে পাই ৩..6 + ডিক্টস পরিবর্তন হয়েছিল তার একটি নিখরচায় বৈশিষ্ট্য নয়। OrderedDictআপনি অর্ডার যত্ন যদি ব্যবহার করুন ।
গ্রানিতোসরাস

2
ধন্যবাদ @ গ্রানিতোসরাস, আপনার আমার কাছে এটি ব্যাখ্যা করার দরকার নেই। এটা আমার মন্তব্যের মূল বিষয় ছিল না।
szeitlin

5
@ সিতিটলিন আপনার মন্তব্যে বোঝানো হয়েছে যে ডিক্ট অর্ডারটি কোনওভাবে, আকার বা রূপের ক্ষেত্রে পরিবর্তন করে যখন বাস্তবে কেউ অভিধানের আদেশের উপর নির্ভর না করে তাই এই সত্যটি সম্পূর্ণ অপ্রাসঙ্গিক
Granitosaurus

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
@ মেরোজ আপনার মডিউল অনুসন্ধানের পথে পাইথন ফাইলটি কোথাও যুক্ত করুন এবং 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

অন্যান্য উত্তরগুলি বেশ ভাল। তবে পাইথন ৩..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

পাইথন ৩.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বিবৃতি ব্যতীত আইপথন কনসোল / বৃহস্পতি নোটবুক তাদের অভিধানের পছন্দ অনুযায়ী অভিধানটি উপস্থাপন করে ...


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

কীগুলির নাম পরিবর্তন করার সময় আমি ডিক.পপ () এর সাথে উপরের @ উইমের উত্তরটি ব্যবহার করছি, তবে আমি একটি গোটচা পেয়েছি। পুরানো কীগুলির তালিকাকে ডিকের উদাহরণ থেকে সম্পূর্ণ আলাদা না করেই কীগুলি পরিবর্তন করতে ডিকের মাধ্যমে সাইকেল চালানো, ফলে সাইক্লিংয়ের ফলে নতুন, পরিবর্তিত চাবিগুলি লুপে পরিবর্তিত হয় এবং কিছু বিদ্যমান কী হারিয়ে যায়।

শুরু করার জন্য, আমি এটি এইভাবে করেছি:

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 কে কে 4 এ নামকরণ করতে চান:

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তবে আপনার বন্ধনী নয়, স্কয়ার বন্ধনী ব্যবহার করা উচিত। তবে এটি কেবল অভিধানে একটি নতুন কী যুক্ত করবে এবং অনুরোধ অনুসারে কোনও বিদ্যমান কীটির নাম পরিবর্তন করবে না।
জুঁই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.