বিবিধ গভীরতার নেস্টেড অভিধানের আপডেট মান


162

আমি ওভাররাইটিং স্তরএবং ডিক আপডেটের বিষয়বস্তু সহ ডিক ডিকশনারি 1 আপডেট করার উপায় খুঁজছি

dictionary1={'level1':{'level2':{'levelA':0,'levelB':1}}}
update={'level1':{'level2':{'levelB':10}}}
dictionary1.update(update)
print dictionary1
{'level1': {'level2': {'levelB': 10}}}

আমি জানি যে আপডেটটি লেভেল 2 এর মানগুলি মুছে দেয় কারণ এটি সর্বনিম্ন কী স্তরের 1 আপডেট করে।

অভিধান 1 এবং আপডেটের কোনও দৈর্ঘ্য থাকতে পারে, আমি কীভাবে এটি সামাল দিতে পারি?


বাসা বাঁধতে সর্বদা তিনটি স্তর গভীর হয় বা আপনি নির্বিচারে গভীরতার নীড় বাঁধতে পারেন?
ক্রিস্টোফিড

এটির যে কোনও গভীরতা / দৈর্ঘ্য থাকতে পারে।
jay_t

আমি ভুল হলে আমাকে সংশোধন করুন তবে মনে হচ্ছে এখানে আদর্শ সমাধানের জন্য সম্মিলিত ডিজাইনের প্যাটার্ন প্রয়োগ করা দরকার।
আলেকজান্ডার ম্যাকএনট্রি

একটি নতুন প্রশ্ন stackoverflow.com/questions/59004746/...
user7337353

উত্তর:


263

@ এফএম এর উত্তরের সঠিক সাধারণ ধারণা রয়েছে, অর্থাত একটি পুনরাবৃত্ত সমাধান, তবে কিছুটা অদ্ভুত কোডিং এবং কমপক্ষে একটি বাগ। পরিবর্তে আমি সুপারিশ করব:

পাইথন 2:

import collections

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, collections.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

পাইথন 3:

import collections.abc

def update(d, u):
    for k, v in u.items():
        if isinstance(v, collections.abc.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

"আপডেট" থাকে যখন বাগটি প্রদর্শিত হয় k , vআইটেম যেখানে vথাকে dictএবং kমূলত আপডেট হওয়া অভিধানের মূল কী নয় - - @ এফএম এর কোড আপডেটের এই অংশটিকে "এড়িয়ে যায়" (কারণ এটি খালি নতুনটিতে এটি সম্পাদন করে)dict যা সংরক্ষিত বা কোথাও ফিরে আসে নি, কেবল পুনরাবৃত্তি কল ফিরে আসার পরে হারিয়ে গেছে)।

আমার অন্যান্য পরিবর্তনগুলি সামান্য: যখন একই কাজটি দ্রুত এবং পরিষ্কার করে তখন if/ elseনির্মাণের কোনও কারণ .getনেই এবংisinstance সাধারণতার জন্য অ্যাবস্ট্রাক্ট বেস ক্লাসগুলিতে (কংক্রিটগুলি নয়) সর্বোত্তমভাবে প্রয়োগ করা হয়।


7
+1 বাগে ভাল ধরা - দোহ! আমি অনুভব করেছি যে কারও কাছে isinstanceপরীক্ষাটি পরিচালনা করার আরও ভাল উপায় হবে তবে আমি ভেবেছিলাম যে আমি এটির জন্য ছুরিকাঘাত করব।
এফএমসি

6
আর একটি ছোটখাটো "বৈশিষ্ট্য" এটি উত্থাপনের কারণ TypeError: 'int' object does not support item assignment.যখন আপনি, যেমন update({'k1': 1}, {'k1': {'k2': 2}})। এই আচরণটি পরিবর্তন করতে এবং এর পরিবর্তে অভিধানের গভীরতা প্রসারিত করুন গভীর অভিধানের জন্য জায়গা তৈরি করার জন্য আপনি শর্তের elif isinstance(d, Mapping):চারপাশে d[k] = u[k]এবং পরে একটি যোগ করতে পারেন isinstanceelse: d = {k: u[k]}আপডেট ডেকটি মূল ডিকের চেয়েও গভীর যে কেসটি মোকাবেলা করার জন্য আপনাকে একটি যুক্ত করতে হবে। উত্তরটি সম্পাদনা করতে পেরে খুশি, কিন্তু অপ্রচলিত সংক্ষিপ্ত কোডটি খুলতে চান না যা ওপির সমস্যার সমাধান করে।
hobs

1
এর isinstance(v, collections.Mapping)চেয়ে কেন ব্যবহার করবেন isinstance(v, dict)? ওপিতে সংগ্রহগুলি ব্যবহার শুরু করার সিদ্ধান্ত নিয়েছে?
ম্যাট

2
@ ম্যাট ইয়ে, বা অন্য কোনও ম্যাপিং-উত্পন্ন বস্তু (জিনিসগুলির জোড়া তালিকাগুলি)। ফাংশনটিকে আরও সাধারণ করে তোলে এবং ম্যাপিং-উত্পন্ন বস্তুগুলিকে চুপচাপ উপেক্ষা করে এবং সেগুলি আপডেট না করে ছেড়ে দেয় (অপ্রত্যাশিত ত্রুটি যা ওপি কখনও দেখতে পাবে না / ধরতে পারে)। আপনি প্রায় সবসময় ড্রেপ প্রকার এবং বেস স্ট্রিংগুলি অনুসন্ধানের জন্য ম্যাপিং ব্যবহার করতে চান।
hobs

2
আপনি যদি পাইথন 3+ এর অধীনে এটি চালিয়ে u.iteritems()যান তবে u.items()অন্যথায় আপনি মুখোমুখি হবেন:AttributeError: 'dict' object has no attribute 'iteritems'
গ্রেগ কে

23

আমাকে এইটি সম্পর্কে একটু একটু করে নিয়েছে, কিন্তু @ অ্যালেক্সের পোস্টের জন্য ধন্যবাদ, আমি যে শূন্যস্থানটি হারিয়েছিলাম তা পূরণ করে। যাইহোক, আমি একটি বিষয় জুড়ে এসেছিল যদি রিকার্সিভ মধ্যে একটি মান dictএকটি হতে হবে list, তাই আমি ভাবলাম ভাগ চাই, এবং তার উত্তর প্রসারিত।

import collections

def update(orig_dict, new_dict):
    for key, val in new_dict.iteritems():
        if isinstance(val, collections.Mapping):
            tmp = update(orig_dict.get(key, { }), val)
            orig_dict[key] = tmp
        elif isinstance(val, list):
            orig_dict[key] = (orig_dict.get(key, []) + val)
        else:
            orig_dict[key] = new_dict[key]
    return orig_dict

3
আমি মনে করি এটি সম্ভবত হওয়া উচিত (কিছুটা নিরাপদ হওয়ার জন্য) : orig_dict.get(key, []) + val.
অ্যান্ডি হেডেন

2
যেহেতু ডিকটগুলি পরিবর্তনযোগ্য, তাই আপনি যে দৃষ্টান্তটি তর্ক হিসাবে পাস করছেন তা পরিবর্তন করছেন। তারপরে, আপনার অরিজিন_ডিক্টটি ফেরানোর দরকার নেই।
gabrielhpugliese

3
আমি মনে করি বেশিরভাগ লোকেরা স্থানে আপডেট হওয়া সত্ত্বেও সংজ্ঞাটি আপডেট ডিকটি ফিরিয়ে দেওয়ার প্রত্যাশা করবে।
কেল সোলার

ওনোসেন্ডির কোডের ডিফল্ট যুক্তি হ'ল আপডেট তালিকাকে মূল তালিকায় যুক্ত করা। যদি আপনাকে মূল তালিকাটি ওভাররাইট আপডেট করতে হয় তবে আপনাকে অরিজিন_ডিক্ট [কী] = ভাল
ইন্টিজক

1
merged_tree = update({'default': {'initialvalue': 1}}, other_tree)
@ গ্যাব্রিলহপুগলিজ

18

@ অ্যালেক্সের উত্তরটি ভাল, তবে কোনও অভিধানের সাথে একটি পূর্ণসংখ্যার মতো কোনও উপাদান যেমন প্রতিস্থাপন করার সময় কাজ করে না update({'foo':0},{'foo':{'bar':1}})। এই আপডেট এটি ঠিকানা:

import collections
def update(d, u):
    for k, v in u.iteritems():
        if isinstance(d, collections.Mapping):
            if isinstance(v, collections.Mapping):
                r = update(d.get(k, {}), v)
                d[k] = r
            else:
                d[k] = u[k]
        else:
            d = {k: u[k]}
    return d

update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})

আমি দেখি. আপনি আমার elifমূল বস্তুর টাইপ করে একটি "এনক্লোজিং" শর্তসাপেক্ষ শর্তসাপেক্ষে মূল্য এবং সেই ডিক / ম্যাপিংয়ের কী উভয়ই যাচাই করেছেন। চালাক।
hobs

যদি অভ্যন্তরীণ নির্দেশে একাধিক কী থাকে তবে এটি কাজ করবে না।
উইলিন

@ ওয়ার্লিন, এটি এখনও কাজ করে; d সেই বিন্দুতে ম্যাপিং হয়ে উঠবে। এখানে একাধিক কী এর মাধ্যমে একটি পরীক্ষা ক্ষেত্রে: update({'A1': 1, 'A2':2}, {'A1': {'B1': {'C1': 3, 'C2':4}, 'B2':2}, 'A3':5})। আপনার কি এমন উদাহরণ রয়েছে যা আপনি চান তা করেন না?
বিএসসিএন

if isinstance(d, collections.Mapping)ইভটি পুনরাবৃত্তির উপর পরীক্ষা কেন ? আমার উত্তর দেখুন ।
জেরুমে

13

গৃহীত হিসাবে একই সমাধান, তবে পরিষ্কার ভেরিয়েবল নামকরণ, ডকস্ট্রিং, এবং একটি বাগ ঠিক করা যেখানে {}মান হিসাবে ওভাররাইড হবে না।

import collections


def deep_update(source, overrides):
    """
    Update a nested dictionary or similar mapping.
    Modify ``source`` in place.
    """
    for key, value in overrides.iteritems():
        if isinstance(value, collections.Mapping) and value:
            returned = deep_update(source.get(key, {}), value)
            source[key] = returned
        else:
            source[key] = overrides[key]
    return source

এখানে কয়েকটি পরীক্ষার মামলা রয়েছে:

def test_deep_update():
    source = {'hello1': 1}
    overrides = {'hello2': 2}
    deep_update(source, overrides)
    assert source == {'hello1': 1, 'hello2': 2}

    source = {'hello': 'to_override'}
    overrides = {'hello': 'over'}
    deep_update(source, overrides)
    assert source == {'hello': 'over'}

    source = {'hello': {'value': 'to_override', 'no_change': 1}}
    overrides = {'hello': {'value': 'over'}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': 'over', 'no_change': 1}}

    source = {'hello': {'value': 'to_override', 'no_change': 1}}
    overrides = {'hello': {'value': {}}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': {}, 'no_change': 1}}

    source = {'hello': {'value': {}, 'no_change': 1}}
    overrides = {'hello': {'value': 2}}
    deep_update(source, overrides)
    assert source == {'hello': {'value': 2, 'no_change': 1}}

এই ফাংশন পাওয়া যায় হাতুড়ে ডাক্তার প্যাকেজ, মধ্যে charlatan.utils


7

এখানে কারওর প্রয়োজন হলে পুনরাবৃত্ত অভিধানের একীকরণের অপরিবর্তিত সংস্করণ's

@ অ্যালেক্স মার্তেলির উত্তরের ভিত্তিতে ।

পাইথন 2.x:

import collections
from copy import deepcopy


def merge(dict1, dict2):
    ''' Return a new dictionary by merging two dictionaries recursively. '''

    result = deepcopy(dict1)

    for key, value in dict2.iteritems():
        if isinstance(value, collections.Mapping):
            result[key] = merge(result.get(key, {}), value)
        else:
            result[key] = deepcopy(dict2[key])

    return result

পাইথন 3.x:

import collections
from copy import deepcopy


def merge(dict1, dict2):
    ''' Return a new dictionary by merging two dictionaries recursively. '''

    result = deepcopy(dict1)

    for key, value in dict2.items():
        if isinstance(value, collections.Mapping):
            result[key] = merge(result.get(key, {}), value)
        else:
            result[key] = deepcopy(dict2[key])

    return result

6

@ অ্যালেক্সের উত্তরে ছোটখাটো উন্নতি যা বিভিন্ন গভীরতার অভিধানের আপডেট আপডেট করতে সক্ষম করে এবং সেই গভীরতাকে সীমাবদ্ধ করে যে আপডেটটি মূল নেস্টেড অভিধানে ডাইভ করে (তবে আপডেট করার অভিধানের গভীরতা সীমাবদ্ধ নয়)। কয়েকটি কয়েকটি ক্ষেত্রেই পরীক্ষা করা হয়েছে:

def update(d, u, depth=-1):
    """
    Recursively merge or update dict-like objects. 
    >>> update({'k1': {'k2': 2}}, {'k1': {'k2': {'k3': 3}}, 'k4': 4})
    {'k1': {'k2': {'k3': 3}}, 'k4': 4}
    """

    for k, v in u.iteritems():
        if isinstance(v, Mapping) and not depth == 0:
            r = update(d.get(k, {}), v, depth=max(depth - 1, -1))
            d[k] = r
        elif isinstance(d, Mapping):
            d[k] = u[k]
        else:
            d = {k: u[k]}
    return d

1
এর জন্য ধন্যবাদ! গভীরতার পরামিতি কী ব্যবহারের ক্ষেত্রে প্রয়োগ হতে পারে?
ম্যাট

@ ম্যাট যখন আপনার পরিচিত বস্তু / ডিক্টগুলি একটি গভীর গভীরতায় থাকে যা আপনি মার্জ / আপডেট করতে চান না, কেবলমাত্র নতুন অবজেক্টের সাথে ওভাররাইট করুন (যেমন ডিকের প্রতিস্থাপন যেমন স্ট্রিং বা ভাসা বা যা কিছু আপনার ডিকের গভীরে)
হবস

1
এটি কেবলমাত্র তখনই কার্যকর হয় যখন আপডেটটি মূলের চেয়ে কমপক্ষে 1 স্তর গভীর হয়। উদাহরণস্বরূপ, এটি ব্যর্থ: update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})আমি একটি উত্তর যুক্ত করেছি যা এতে সম্বোধন করে
bscan

@ বিস্ক্যান ভাল ধরা! যে ব্যবহারের ক্ষেত্রে কখনও ভাবেনি। আমার ধারণা, এলিফ শাখাগুলিতে আরও গভীর পুনরাবৃত্তি করা উচিত। কোন ধারনা?
hobs

if isinstance(d, Mapping)ইভটি পুনরাবৃত্তির উপর পরীক্ষা কেন ? আমার উত্তর দেখুন । (এছাড়াও, আমি আপনার সম্পর্কে নিশ্চিত নই d = {k: u[k]})
জেরমে

4

এই প্রশ্নটি পুরানো, তবে "গভীর সংশ্লেষ" সমাধান অনুসন্ধান করার সময় আমি এখানে অবতরণ করেছি। উপরের উত্তরগুলি অনুসরণ করে যা অনুপ্রাণিত করে। আমি আমার নিজের লেখাটি শেষ করেছি কারণ আমার পরীক্ষিত সমস্ত সংস্করণগুলিতে বাগ রয়েছে। যে সমালোচনামূলক বিষয়টি হাতছাড়া হয়েছিল তা হ'ল দুটি ইনপুট ডিক্টের স্বেচ্ছাসেবী গভীরতায় কিছু কী, কে, সিদ্ধান্ত গাছ যখন ডি [কে] বা আপনি [কে] ডিক্ট ত্রুটিযুক্ত ছিল না

এছাড়াও, এই সমাধানটির পুনরাবৃত্তি প্রয়োজন হয় না, যা কীভাবে dict.update()কাজ করে এবং আরও ফিরে আসে তার সাথে আরও প্রতিসাম্য None

import collections
def deep_merge(d, u):
   """Do a deep merge of one dict into another.

   This will update d with values in u, but will not delete keys in d
   not found in u at some arbitrary depth of d. That is, u is deeply
   merged into d.

   Args -
     d, u: dicts

   Note: this is destructive to d, but not u.

   Returns: None
   """
   stack = [(d,u)]
   while stack:
      d,u = stack.pop(0)
      for k,v in u.items():
         if not isinstance(v, collections.Mapping):
            # u[k] is not a dict, nothing to merge, so just set it,
            # regardless if d[k] *was* a dict
            d[k] = v
         else:
            # note: u[k] is a dict

            # get d[k], defaulting to a dict, if it doesn't previously
            # exist
            dv = d.setdefault(k, {})

            if not isinstance(dv, collections.Mapping):
               # d[k] is not a dict, so just set it to u[k],
               # overriding whatever it was
               d[k] = v
            else:
               # both d[k] and u[k] are dicts, push them on the stack
               # to merge
               stack.append((dv, v))

4

কেবল ব্যবহার করুন python-benedict (আমি এটি করেছি) , এটির merge(ডিপআপডেট) ইউটিলিটি পদ্ধতি এবং আরও অনেকগুলি রয়েছে। এটি পাইথন 2 / পাইথন 3 এর সাথে কাজ করে এবং এটি ভাল পরীক্ষা করা হয়।

from benedict import benedict

dictionary1=benedict({'level1':{'level2':{'levelA':0,'levelB':1}}})
update={'level1':{'level2':{'levelB':10}}}
dictionary1.merge(update)
print(dictionary1)
# >> {'level1':{'level2':{'levelA':0,'levelB':10}}}

স্থাপন: pip install python-benedict

ডকুমেন্টেশন: https://github.com/fabiocaccamo/python-benedict


2

এই উত্তরের কোনওটিতেই লেখকরা অভিধানে সঞ্চিত কোনও অবজেক্ট আপডেট করার বা অভিধানের আইটেমগুলিতে পুনরুক্তি করার ধারণাটি (কীগুলির বিপরীতে) বুঝতে পেরেছেন বলে মনে হয়। সুতরাং আমাকে এমন একটি লিখতে হয়েছিল যা অর্থহীন টোটোলজিকাল অভিধানের দোকান এবং পুনরুদ্ধার করে না। ডিক্টগুলি অন্যান্য ডিকট বা সাধারণ ধরণের সঞ্চয় করার জন্য ধারনা করা হয়।

def update_nested_dict(d, other):
    for k, v in other.items():
        if isinstance(v, collections.Mapping):
            d_v = d.get(k)
            if isinstance(d_v, collections.Mapping):
                update_nested_dict(d_v, v)
            else:
                d[k] = v.copy()
        else:
            d[k] = v

বা এমনকি সহজ যে কোনও ধরণের সাথে কাজ করছে:

def update_nested_dict(d, other):
    for k, v in other.items():
        d_v = d.get(k)
        if isinstance(v, collections.Mapping) and isinstance(d_v, collections.Mapping):
            update_nested_dict(d_v, v)
        else:
            d[k] = deepcopy(v) # or d[k] = v if you know what you're doing

2

সমাধান আরও দৃ make় করতে তার কোডে একটি বাগ ঠিক করার জন্য @ অ্যালেক্স মার্তেলির জবাব আপডেট করুন:

def update_dict(d, u):
    for k, v in u.items():
        if isinstance(v, collections.Mapping):
            default = v.copy()
            default.clear()
            r = update_dict(d.get(k, default), v)
            d[k] = r
        else:
            d[k] = v
    return d

মূলটি হ'ল আমরা প্রায়শই একই ধরণের পুনরাবৃত্তিতে তৈরি করতে চাই , সুতরাং এখানে আমরা ব্যবহার করি v.copy().clear()তবে তা নয় {}। এবং এটি বিশেষত কার্যকর যদি dictএখানে টাইপ হয় collections.defaultdictযা বিভিন্ন ধরণের default_factoryএস থাকতে পারে।

এছাড়াও লক্ষ্য করুন যে u.iteritems()এটিতে পরিবর্তন করা u.items()হয়েছে Python3


2

আমি অ্যালেক্স মার্তেলির পরামর্শ হিসাবে সমাধানটি ব্যবহার করেছি, তবে এটি ব্যর্থ হয়

TypeError 'bool' object does not support item assignment

যখন দুটি অভিধানের কোনও স্তরে ডেটা টাইপ আলাদা হয়।

একই স্তরের ক্ষেত্রে অভিধানের উপাদানটি dকেবল একটি স্কেলার (অর্থাত্‍ Bool) থাকে যখন uঅভিধানের উপাদানটি এখনও অভিধান হয় পুনরায় নিয়োগের ক্ষেত্রে ব্যর্থ হয় কারণ অভিধানের কোনও অ্যাসাইনমেন্ট স্ক্যালারের (যেমন True[k]) তে সম্ভব না ।

একটি যুক্ত শর্ত ঠিক করে যে:

from collections import Mapping

def update_deep(d, u):
    for k, v in u.items():
        # this condition handles the problem
        if not isinstance(d, Mapping):
            d = u
        elif isinstance(v, Mapping):
            r = update_deep(d.get(k, {}), v)
            d[k] = r
        else:
            d[k] = u[k]

    return d

2

নীচের কোডটি update({'k1': 1}, {'k1': {'k2': 2}})@ অ্যালেক্স মার্তেলির উত্তরটি সঠিকভাবে দেওয়া উচিত ।

def deepupdate(original, update):
    """Recursively update a dict.

    Subdict's won't be overwritten but also updated.
    """
    if not isinstance(original, abc.Mapping):
        return update
    for key, value in update.items():
        if isinstance(value, abc.Mapping):
            original[key] = deepupdate(original.get(key, {}), value)
        else:
            original[key] = value
    return original

1
def update(value, nvalue):
    if not isinstance(value, dict) or not isinstance(nvalue, dict):
        return nvalue
    for k, v in nvalue.items():
        value.setdefault(k, dict())
        if isinstance(v, dict):
            v = update(value[k], v)
        value[k] = v
    return value

ব্যবহার dictবাcollections.Mapping


1

আমি জানি এই প্রশ্নটি বেশ পুরানো, তবে এখনও যখন আমি নেস্টেড ডিকশনারিটি আপডেট করতে হয় তখন আমি কী পোস্ট করি ing আমরা এই সত্যটি ব্যবহার করতে পারি যে পাইকের পথটি পরিচিত এবং বিন্দুটি পৃথক হয়েছে তা ধরে নিয়ে অজগরটি রেফারেন্স দিয়ে রেখেছে। বৈদেশিক মুদ্রার যদি আমাদের কাছে ডিক্ট নামের একটি ডেটা থাকে:

{
"log_config_worker": {
    "version": 1, 
    "root": {
        "handlers": [
            "queue"
        ], 
        "level": "DEBUG"
    }, 
    "disable_existing_loggers": true, 
    "handlers": {
        "queue": {
            "queue": null, 
            "class": "myclass1.QueueHandler"
        }
    }
}, 
"number_of_archived_logs": 15, 
"log_max_size": "300M", 
"cron_job_dir": "/etc/cron.hourly/", 
"logs_dir": "/var/log/patternex/", 
"log_rotate_dir": "/etc/logrotate.d/"
}

এবং আমরা সারি শ্রেণি আপডেট করতে চাই, কীটির পথটি হবে - log_config_worker.handlers.queue.class

মানটি আপডেট করার জন্য আমরা নিম্নলিখিত ফাংশনটি ব্যবহার করতে পারি:

def get_updated_dict(obj, path, value):
    key_list = path.split(".")

    for k in key_list[:-1]:
        obj = obj[k]

    obj[key_list[-1]] = value

get_updated_dict(data, "log_config_worker.handlers.queue.class", "myclass2.QueueHandler")

এটি অভিধানটিকে সঠিকভাবে আপডেট করবে।


1

এমনও হতে পারে যে আপনি আজ আমার মতো একটি অ-মানক-অভিধানে হোঁচট খাচ্ছেন, যার কোনও ইটারাইটামস-অ্যাট্রিবিউট নেই। এক্ষেত্রে এই ধরণের অভিধানটিকে একটি স্ট্যান্ডার্ড-অভিধান হিসাবে ব্যাখ্যা করা সহজ। উদাহরণস্বরূপ: পাইথন ২.7:

    import collections
    def update(orig_dict, new_dict):
        for key, val in dict(new_dict).iteritems():
            if isinstance(val, collections.Mapping):
                tmp = update(orig_dict.get(key, { }), val)
                orig_dict[key] = tmp
            elif isinstance(val, list):
                orig_dict[key] = (orig_dict[key] + val)
            else:
                orig_dict[key] = new_dict[key]
        return orig_dict

    import multiprocessing
    d=multiprocessing.Manager().dict({'sample':'data'})
    u={'other': 1234}

    x=update(d, u)
    x.items()

পাইথন ৩.৮:

    def update(orig_dict, new_dict):
        orig_dict=dict(orig_dict)
        for key, val in dict(new_dict).items():
            if isinstance(val, collections.abc.Mapping):
                tmp = update(orig_dict.get(key, { }), val)
                orig_dict[key] = tmp
            elif isinstance(val, list):
                orig_dict[key] = (orig_dict[key] + val)
            else:
                orig_dict[key] = new_dict[key]
        return orig_dict

    import collections
    import multiprocessing
    d=multiprocessing.Manager().dict({'sample':'data'})
    u={'other': 1234, "deeper": {'very': 'deep'}}

    x=update(d, u)
    x.items()

0

হ্যাঁ! এবং অন্য একটি সমাধান। আমার সমাধানগুলি যাচাই করা হচ্ছে কীগুলির মধ্যে পৃথক। অন্যান্য সমস্ত সমাধানগুলিতে আমরা কেবল কীগুলি দেখি dict_b। তবে এখানে আমরা উভয় অভিধানের মিলকে দেখি।

আপনি দয়া করে এটি সঙ্গে করুন

def update_nested(dict_a, dict_b):
    set_keys = set(dict_a.keys()).union(set(dict_b.keys()))
    for k in set_keys:
        v = dict_a.get(k)
        if isinstance(v, dict):
            new_dict = dict_b.get(k, None)
            if new_dict:
                update_nested(v, new_dict)
        else:
            new_value = dict_b.get(k, None)
            if new_value:
                dict_a[k] = new_value

0

আপনি যদি "অ্যারেগুলির সাথে পূর্ণ নেস্টেড ডিকশনারি" প্রতিস্থাপন করতে চান তবে আপনি এই স্নিপেটটি ব্যবহার করতে পারেন:

এটি "new_value" দ্বারা যে কোনও "old_value" প্রতিস্থাপন করবে। এটি অভিধানের গভীরতার সাথে প্রথম পুনর্নির্মাণ করছে। এটি এমনকি প্রথম স্তরের ইনপুট প্যারামিটার হিসাবে দেওয়া তালিকা বা স্ট্রিং / ইন্টের সাথেও কাজ করতে পারে।

def update_values_dict(original_dict, future_dict, old_value, new_value):
    # Recursively updates values of a nested dict by performing recursive calls

    if isinstance(original_dict, Dict):
        # It's a dict
        tmp_dict = {}
        for key, value in original_dict.items():
            tmp_dict[key] = update_values_dict(value, future_dict, old_value, new_value)
        return tmp_dict
    elif isinstance(original_dict, List):
        # It's a List
        tmp_list = []
        for i in original_dict:
            tmp_list.append(update_values_dict(i, future_dict, old_value, new_value))
        return tmp_list
    else:
        # It's not a dict, maybe a int, a string, etc.
        return original_dict if original_dict != old_value else new_value

0

পুনরাবৃত্তি ব্যবহারের আরেকটি উপায়:

def updateDict(dict1,dict2):
    keys1 = list(dict1.keys())
    keys2= list(dict2.keys())
    keys2 = [x for x in keys2 if x in keys1]
    for x in keys2:
        if (x in keys1) & (type(dict1[x]) is dict) & (type(dict2[x]) is dict):
            updateDict(dict1[x],dict2[x])
        else:
            dict1.update({x:dict2[x]})
    return(dict1)

0

একটি নতুন প্রশ্ন কিভাবে একটি চেইন শৃঙ্খল দ্বারা

dictionary1={'level1':{'level2':{'levelA':0,'levelB':1}},'anotherLevel1':{'anotherLevel2':{'anotherLevelA':0,'anotherLevelB':1}}}
update={'anotherLevel1':{'anotherLevel2':1014}}
dictionary1.update(update)
print dictionary1
{'level1':{'level2':{'levelA':0,'levelB':1}},'anotherLevel1':{'anotherLevel2':1014}}

0

আপনি এটি চেষ্টা করতে পারেন, এটি তালিকাগুলির সাথে কাজ করে এবং খাঁটি:

def update_keys(newd, dic, mapping):
  def upsingle(d,k,v):
    if k in mapping:
      d[mapping[k]] = v
    else:
      d[k] = v
  for ekey, evalue in dic.items():
    upsingle(newd, ekey, evalue)
    if type(evalue) is dict:
      update_keys(newd, evalue, mapping)
    if type(evalue) is list:
      upsingle(newd, ekey, [update_keys({}, i, mapping) for i in evalue])
  return newd

0

আমি প্রতিস্থাপন করতে সুপারিশ {}দ্বারা type(v)()কোনো অভি উপশ্রেণী সঞ্চিত এর বংশ বিস্তার অবজেক্ট প্রকারটি করার জন্য uকিন্তু অনুপস্থিত d। উদাহরণস্বরূপ, এটি সংগ্রহের মতো ধরণের সংরক্ষণ করবে Oআরআরডিক্ট:

পাইথন 2:

import collections

def update(d, u):
    for k, v in u.iteritems():
        if isinstance(v, collections.Mapping):
            d[k] = update(d.get(k, type(v)()), v)
        else:
            d[k] = v
    return d

পাইথন 3:

import collections.abc

def update(d, u):
    for k, v in u.items():
        if isinstance(v, collections.abc.Mapping):
            d[k] = update(d.get(k, type(v)()), v)
        else:
            d[k] = v
    return d

-1

এটি কিছুটা দিক তবে আপনার কী নেস্টেড ডিকশনারি দরকার? সমস্যার উপর নির্ভর করে, কখনও কখনও ফ্ল্যাট অভিধান পর্যাপ্ত হতে পারে ... এবং এটিকে দেখতে ভাল লাগবে:

>>> dict1 = {('level1','level2','levelA'): 0}
>>> dict1['level1','level2','levelB'] = 1
>>> update = {('level1','level2','levelB'): 10}
>>> dict1.update(update)
>>> print dict1
{('level1', 'level2', 'levelB'): 10, ('level1', 'level2', 'levelA'): 0}

5
নেস্টেড কাঠামো আগত জসন ডেটাসেট থেকে এসেছে, সুতরাং আমি তাদের অক্ষত রাখতে চাই, ...
জয়_t

-1

যদি আপনি ওয়ান-লাইনার চান:

{**dictionary1, **{'level1':{**dictionary1['level1'], **{'level2':{**dictionary1['level1']['level2'], **{'levelB':10}}}}}}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.