পাইথনে আমি কীভাবে অভিধানগুলিকে একত্রিত করব?


91
d3 = dict(d1, **d2)

আমি বুঝতে পারি যে এটি অভিধানকে একীভূত করে। তবে, এটি কি অনন্য? যদি ডি 1 এর একই কী কী ডি 2 তবে ভিন্ন মান থাকে? আমি d1 এবং d2 একত্রিত করতে চাই, তবে ডুপ্লিকেট কী থাকলে ডি 1 এর অগ্রাধিকার রয়েছে।


9
দয়া করে সচেতন হন যে এই কৌশলটি **কীওয়ার্ড আর্গুমেন্টের অপব্যবহার হিসাবে বিবেচিত হবে যদি না সমস্ত কীগুলি d2স্ট্রিং না হয়। যদি সমস্ত কীগুলি d2স্ট্রিং না হয় তবে পাইথন ৩.২ এ এটি ব্যর্থ হয় এবং পাইথনের বিকল্প বাস্তবায়নে যেমন জাইথন, আয়রন পাইথন এবং পাইপাই। উদাহরণস্বরূপ, mail.python.org/pipermail/python-dev/2010- এপ্রিল / 099459 . html দেখুন
মার্ক ডিকিনসন

উত্তর:


154

আপনি ব্যবহার করতে পারেন .update()আপনার আর আর মূল প্রয়োজন না থাকলে আপনি পদ্ধতিটিd2 :

বিদ্যমান কীগুলি ওভাররাইট করে অন্যের কী / মান জোড় দিয়ে অভিধানটি আপডেট করুন । রিটার্ন None

যেমন:

>>> d1 = {'a': 1, 'b': 2} 
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}

হালনাগাদ:

একটি নতুন মার্জড তৈরির জন্য অবশ্যই আপনি অভিধানটি অনুলিপি করতে পারেন। এটি প্রয়োজন বা নাও হতে পারে। আপনার অভিধানে যৌগিক অবজেক্টস (অন্যান্য বিষয়বস্তুগুলির তালিকা, বা শ্রেণীর উদাহরণগুলির মতো পদার্থ) রয়েছে copy.deepcopyসে ক্ষেত্রেও বিবেচনা করা উচিত।


4
এই ক্ষেত্রে ডি -1 উপাদানগুলি বিরোধী কীগুলি পাওয়া গেলে সঠিকভাবে অগ্রাধিকার পাওয়া উচিত
ট্রে হানার

আপনার যদি এখনও এটির প্রয়োজন হয় তবে কেবল একটি অনুলিপি তৈরি করুন। d3 = d2.copy () d3.update (d1) তবে আমি দেখতে চাই D1 + d2 ভাষার সাথে যুক্ত হচ্ছে।
স্টাচ

4
ডি 1 + ডি 2 সমস্যাযুক্ত কারণ একটি অভিধানে দ্বন্দ্ব চলাকালীন অগ্রাধিকার থাকতে হয় এবং এটি কোনটি বিশেষভাবে স্পষ্ট নয়।
rjh

পাইথন কোনও মাল্টিম্যাপ অর্জন করলেই ডি 1 + ডি 2 কেবল কার্যকর হবে, অন্যথায় ব্যবহারকারীর কাছে অস্পষ্টতা 8 বাইট টাইপিং লাভের জন্য খুব বিভ্রান্তিকর।
নিক বাস্টিন

এই উদাহরণে আপনার অভিধানের মধ্যে অবজেক্ট রয়েছে: isinstance(int, object) is Trueতবে deepcopyপ্রয়োজনীয় মনে হচ্ছে না।
অ্যান্টনি হ্যাচকিন্স

43

পাইথন 2 এ,

d1={'a':1,'b':2}
d2={'a':10,'c':3}

d1 ওভাররাইড ডি 2:

dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}

d2 ওভাররাইড ডি 1:

dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}

এই আচরণটি বাস্তবায়নের এক মাত্রা নয়; এটি ডকুমেন্টেশনে গ্যারান্টিযুক্ত :

যদি কোনও কী উভয় অবস্থানগত আর্গুমেন্টে এবং কীওয়ার্ড আর্গুমেন্ট হিসাবে নির্দিষ্ট করা থাকে, অভিধানে কীওয়ার্ডের সাথে সম্পর্কিত মানটি বজায় রাখা হয়।


4
পাইথন ৩.২-এ আপনার উদাহরণগুলি (টাইপররার উত্পাদন করে) ব্যর্থ হবে এবং জাইথন, পাইপাই এবং আয়রন পাইথনের বর্তমান সংস্করণগুলিতে: পাইথনের সেই সংস্করণগুলির জন্য, **স্বরলিপি সহ একটি ডিক পাস করার সময় সেই ডিকের সমস্ত কী স্ট্রিং হওয়া উচিত। আরও জানতে অজগর-দেব থ্রেডটি mail.python.org/pipermail/python-dev/2010- এপ্রিল/ 099427 . html থেকে শুরু করে দেখুন।
মার্ক ডিকিনসন

@ মার্ক: মাথা আপ জন্য ধন্যবাদ। আমি কোডটি সিপিথন নন-প্রয়োগের সাথে সামঞ্জস্য করার জন্য সম্পাদনা করেছি।
আনটবু

4
আপনার কীগুলি স্ট্রিং এবং সংখ্যার টিপল হলে এটি ব্যর্থ হয়। যেমন। d1 = {(1, 'a'): 1, (1, 'বি'): 0,} d2 = {(1, 'এ'): 1, (2, 'বি'): 2, (2, 'এ'): 1,}
মাইস্কিজো বন্ধু

আনপ্যাকিং সিনট্যাক্স সম্পর্কিত, অজগর 3.5 তে আগত পরিবর্তনগুলির জন্য এই পোস্টটি দেখুন ।
আইওনিস ফিলিপিসিস

আমি যে d = dict(**d1, **d2)কাজ করে তা বলতে যাচ্ছিলাম , কিন্তু এটিই তাদের মন্তব্যে @ ইওনানিস ফিলিপিস রেফারেন্স করে। সম্ভবত এখানে স্নিপেট সহ আরও পরিষ্কার হয়ে যেত, তাই এটি এখানে।
ডোয়ান্ডারসন

14

আপনি যদি d1দ্বন্দ্বগুলিতে অগ্রাধিকার পেতে চান তবে করুন:

d3 = d2.copy()
d3.update(d1)

অন্যথায়, বিপরীত d2এবং d1


1

আমার সমাধানটি হচ্ছে মার্জ ফাংশনটি সংজ্ঞায়িত করা । এটি পরিশীলিত নয় এবং কেবল একটি লাইনের দাম। পাইথন 3 এ কোডটি এখানে।

from functools import reduce
from operator import or_

def merge(*dicts):
    return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }

পরীক্ষা

>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}

এটি অভিধানে যুক্তিগুলি নির্বিচারে কাজ করে। এই অভিধানগুলিতে কোনও সদৃশ কী আছে, তর্ক তালিকার ডানদিকের অভিধান থেকে কীটি জিতেছে।


4
এতে একটি .updateকল সহ একটি সাধারণ লুপ ( merged={}তারপরে for d in dict: merged.update(d)) খাটো হবে, আরও পাঠযোগ্য এবং আরও দক্ষ।
মার্ক ডিকিনসন

4
অথবা আপনি যদি সত্যিই ব্যবহার করতে চান reduceএবং lambdaসেগুলি কীভাবে return reduce(lambda x, y: x.update(y) or x, dicts, {})?
মার্ক ডিকিনসন

4
আপনি শেলটিতে আপনার কোডটি চেষ্টা করে দেখতে পারেন এবং এটি সঠিক কিনা। আমি যা করার চেষ্টা করছিলাম তা হ'ল একটি ফাংশন লিখুন যা একই কার্যকারিতা সহ বিভিন্ন সংখ্যক অভিধান আর্গুমেন্ট নিতে পারে। ল্যাম্বদার নীচে x.update (y) না ব্যবহার করা ভাল, কারণ এটি সর্বদা কোনওটিই দেয় না । এবং আমি আরও একটি সাধারণ ফাংশন মার্জ_ও লিখতে চেষ্টা করছি যা বিভিন্ন সংখ্যক অভিধানের যুক্তি নিয়ে থাকে এবং সরবরাহিত ফাংশনটির সাথে সদৃশ কীগুলির সাথে কাজ করে। আমার কাজ শেষ হয়ে গেলে, আমি এটিকে অন্য থ্রেডে পোস্ট করব যেখানে সমাধানটি আরও প্রাসঙ্গিক।
Lei Zhao

আমি আরও সাধারণ সমাধানটি লিখেছি এখানে লিঙ্কটি । স্বাগতম এবং একটি চেহারা আছে।
Lei Zhao

1

ট্রে হানারের একটি দুর্দান্ত ব্লগ পোস্ট রয়েছে যা একাধিক ডিকশনারি মার্জ করার জন্য বিভিন্ন বিকল্পের রূপরেখার সাথে রয়েছে (পাইথন ৩৩.৩+ এর জন্য) চ্যানম্যাপ এবং অভিধান আনপ্যাকিং সহ


1

শুরু করে Python 3.9, অপারেটর |দুটি অভিধান থেকে মার্জ করা কী এবং মানগুলির সাথে একটি নতুন অভিধান তৈরি করে:

# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}

এই:

ডি 2 এবং ডি 1 এর একত্রীকরণ কী এবং মানগুলির সাহায্যে একটি নতুন অভিধান ডি 3 তৈরি করে। ডি 2 এবং ডি 1 কীগুলি ভাগ করে নেওয়ার সময় ডি 1 এর মানগুলি অগ্রাধিকার নেয়।


এছাড়াও |=অপারেটরটি নোট করুন যা D1 মানগুলিতে অগ্রাধিকার সহ d1 ইন মার্জ করে d2 সংশোধন করে:

# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}


0

আমি বিশ্বাস করি যে, উপরে বর্ণিত হিসাবে, ব্যবহার করা d2.update(d1)হ'ল সর্বোত্তম পন্থা এবং আপনার d2যদি এখনও প্রয়োজন হয় তবে আপনি প্রথমে অনুলিপিও করতে পারেন ।

যদিও, আমি এটি উল্লেখ করতে চাই যে dict(d1, **d2)সাধারণভাবে ডিকশনারিগুলিকে একীভূত করার একটি খারাপ উপায় কারণ মূলশব্দ যুক্তিগুলির স্ট্রিং হওয়া দরকার, সুতরাং আপনার যদি এর dictমতো থাকে তবে এটি ব্যর্থ হবে :

{
  1: 'foo',
  2: 'bar'
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.