কীভাবে "রানটাইম এরর: পুনরাবৃত্তির সময় অভিধানের আকার পরিবর্তন হয়েছে" এড়ানো যায়?


257

আমি একই ত্রুটিযুক্ত অন্যান্য সমস্ত প্রশ্ন যাচাই করেছি তবে এখনও কোনও কার্যকর সমাধান খুঁজে পাইনি = /

আমার কাছে তালিকার একটি অভিধান রয়েছে:

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

যার মধ্যে কিছু মান শূন্য রয়েছে। এই তালিকা তৈরির শেষে, আমি আমার অভিধানটি ফেরত দেওয়ার আগে এই খালি তালিকাগুলি সরাতে চাই। বর্তমান আমি নিম্নলিখিত হিসাবে এটি করার চেষ্টা করছি:

for i in d:
    if not d[i]:
        d.pop(i)

তবে এটি আমাকে রানটাইম ত্রুটি দিচ্ছে giving আমি সচেতন যে আপনি কোনও অভিধানের মাধ্যমে পুনরাবৃত্ত হওয়ার সময় উপাদানগুলিকে যুক্ত / সরিয়ে ফেলতে পারবেন না ... এরপরে কী উপায় হবে?

উত্তর:


453

পাইথন ২.x কল এ keysসংশোধন করার সময় আপনি যে কীটি পুনরাবৃত্তি করতে পারবেন তার একটি অনুলিপি তৈরি করে dict:

for i in d.keys():

দ্রষ্টব্য যে এটি পাইথন ৩.x এ কাজ করে না কারণ keysএকটি তালিকার পরিবর্তে একটি পুনরাবৃত্তি প্রদান করে।

আর একটি উপায় হ'ল listকীগুলি তৈরি করার জন্য জোর করে চাপানো use এটি পাইথন ৩.x এও কাজ করে:

for i in list(d):

1
আমি বিশ্বাস করি আপনি বোঝাতে চেয়েছিলেন 'কলিং কীগুলিkeys অনুলিপি করতে সক্ষম হবে তার চাবিগুলি অনুলিপি করুন ' pluralঠিক কীগুলি? অন্যথায় কীভাবে একটি একক কী ধরে পুনরাবৃত্তি করতে পারে? আমি যেভাবেই বাছাই করছি না, তা সত্যই কী বা কীগুলি তা জানতে সত্যই আগ্রহী
হাইওনমিট

6
বা তালিকার পরিবর্তে টিপল এটি দ্রুত হওয়ায়।
ব্র্যাম্বোর

8
অজগর 3.x এর আচরণ স্পষ্ট করতে, d.keys () একটি পুনরাবৃত্তিযোগ্য (একটি পুনরুক্তিকারী নয়) প্রদান করে যার অর্থ এটি সরাসরি অভিধানের কীগুলিতে একটি দৃশ্য। ব্যবহার for i in d.keys()আসলে পাইথন 3.x কাজ করে সাধারণভাবে , কিন্তু কারণ এটি অভিধানে কীগুলি একজন iterable দৃশ্য উপর iterating করা হয়, কলিং d.pop()হিসাবে আপনি পাওয়া একই ত্রুটির লুপ বিশালাকার হয়েছিল। for i in list(d)আপনার নিজের মতো বিশেষ পরিস্থিতির জন্য পুনরাবৃত্ত হওয়ার আগে তালিকায় কীগুলি অনুলিপি করার জন্য অদক্ষ অজগর 2 আচরণের অনুকরণ করে।
মাইকেল ক্রেবস

আপনার পাইথন 3 সলিউশনটি কাজ করে না যখন আপনি কোনও বস্তু অভ্যন্তরীণ ডিক্টে মুছতে চান। উদাহরণস্বরূপ আপনার ডিক এ তে ডিক এ এবং ডিক বি রয়েছে আপনি যদি
আলী-টি

1
পাইথন 3.x এ, list(d.keys())একই আউটপুট তৈরি করে list(d), কীগুলি রিটার্নে কল listকরে dictkeysকল (যদিও না যে ব্যয়বহুল) অপ্রয়োজনীয়।
সান ব্রেকেনরিজ

46

নতুন ডিকের সাথে প্রাসঙ্গিক আইটেমগুলি অনুলিপি করতে কেবল অভিধান বোধগম্যতা ব্যবহার করুন

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}

পাইথন 3 এ জন্য

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.items() if v}
>>> d
{'a': [1], 'b': [1, 2]}

11
d.iteritems()আমাকে ত্রুটি দিয়েছে আমি d.items()পরিবর্তে ব্যবহার করেছি
পাইথন 3

4
এটি ওপির প্রশ্নে উত্থিত সমস্যার জন্য কাজ করে। তবে যে কেউ এই রানটাইম এরিরটিকে মাল্টি-থ্রেড কোডে আঘাত করার পরে এখানে এসেছেন, সে বিষয়ে সচেতন হন সিপিথনের জিআইএল তালিকা বোধগম্যের মাঝামাঝি সময়েও মুক্তি পেতে পারে এবং আপনাকে এটি অন্যভাবে ঠিক করতে হবে।
ইয়িরখা

40

আপনার কেবল "অনুলিপি" ব্যবহার করতে হবে:

সেই পথে আপনি মূল অভিধান ক্ষেত্রগুলি দিয়ে পুনরাবৃত্তি করতে এবং ফ্লাইতে পছন্দসই ডিক (ডি ডিক) পরিবর্তন করতে পারেন। এটি প্রতিটি অজগর সংস্করণে কাজ করে, তাই এটি আরও স্পষ্ট।

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

In [2]: for i in d.copy():
   ...:     if not d[i]:
   ...:         d.pop(i)
   ...:         

In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}

কাজ করছে! ধন্যবাদ.
গিলহার্ম কারভালহো লিথগ

13

আমি প্রথমে খালি তালিকা inোকানো এড়াতে চেষ্টা করব, তবে, সাধারণত ব্যবহার করব:

d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty

যদি 2.7 এর আগে হয়:

d = dict( (k, v) for k,v in d.iteritems() if v )

বা শুধু:

empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
    del[k]

+1: শেষ বিকল্পটি আকর্ষণীয় কারণ এটি মুছে ফেলা প্রয়োজন এমন আইটেমগুলির কীগুলি কেবল অনুলিপি করে। এটি কেবলমাত্র অল্প সংখ্যক আইটেমকে ডিকের আকারের সাথে সম্পর্কিত মোছার প্রয়োজন হলে এটি আরও ভাল পারফরম্যান্স দিতে পারে।
বায়ার্সকে চিহ্নিত করুন

@ মার্কবায়ার্স হ্যাঁ - এবং যদি বিপুল সংখ্যক এটি করেন তবে ডিকের ফিল্টার করা নতুনটির সাথে পুনরায় বাঁধাই করা একটি ভাল বিকল্প। কাঠামোটি কীভাবে কার্যকর হবে তার প্রত্যাশা সর্বদা
জন ক্লিমেটস

4
রিবন্ডিংয়ের সাথে একটি বিপদটি হ'ল যদি প্রোগ্রামে কোথাও এমন কোনও জিনিস ছিল যা পুরানো ডিকের একটি রেফারেন্স রেখেছিল তবে এটি পরিবর্তনগুলি দেখতে পাবে না। যদি আপনি নিশ্চিত হন যে এটি নয় তবে অবশ্যই ... এটি একটি যুক্তিসঙ্গত পন্থা, তবে এটি বোঝা গুরুত্বপূর্ণ যে এটি মূল ডিকটি সংশোধন করার মতো নয়।
চিহ্নিত করুন বায়ার্স

@ মার্কবায়ার্স অত্যন্ত উত্তম পয়েন্ট - আপনি এবং আমি জানি যে (এবং আরও অনেকে) তবে এটি সবার কাছে সুস্পষ্ট নয়। এবং আমি টেবিলের উপরে অর্থ রাখব এটি আপনাকে পিছনেও কামড় দেয়নি :)
জন ক্লিমেটস

খালি এন্ট্রি সন্নিবেশ করানো এড়ানোর বিন্দুটি খুব ভাল।
ম্যাগনাস বোডিন

12

পাইথন 3 এর জন্য:

{k:v for k,v in d.items() if v}

সুন্দর এবং সংক্ষিপ্ত। পাইথন ২.7 এও আমার জন্য কাজ করেছেন।
ডোনোনডাডন

6

লুপের সময় পরিবর্তিত হওয়ার সময় আপনি কোনও অভিধানের মাধ্যমে পুনরাবৃত্তি করতে পারবেন না। তালিকার জন্য একটি কাস্টিং তৈরি করুন এবং সেই তালিকাটি পুনরাবৃত্তি করুন, এটি আমার পক্ষে কাজ করে।

    for key in list(d):
        if not d[key]: 
            d.pop(key)

1

এর মতো পরিস্থিতিতে আমি মূল ডিকটি সংশোধন করার সময় সেই অনুলিপিটি দিয়ে একটি গভীর অনুলিপি তৈরি করতে এবং লুপ করতে চাই।

যদি অনুসন্ধানের ক্ষেত্রটি কোনও তালিকার মধ্যে থাকে তবে আপনি তালিকার লুপের জন্য গণনা করতে পারেন এবং তারপরে মূল ডিকটিতে ক্ষেত্রটি অ্যাক্সেস করতে সূচক হিসাবে অবস্থানটি নির্দিষ্ট করতে পারেন।


1

এটি আমার পক্ষে কাজ করেছে:

dict = {1: 'a', 2: '', 3: 'b', 4: '', 5: '', 6: 'c'}
for key, value in list(dict.items()):
    if (value == ''):
        del dict[key]
print(dict)
# dict = {1: 'a', 3: 'b', 6: 'c'}  

অভিধানের আইটেমগুলিকে তালিকায় কাস্ট করা তার আইটেমগুলির একটি তালিকা তৈরি করে, যাতে আপনি এটির পুনরাবৃত্তি করতে পারেন এবং এটি এড়াতে পারেন RuntimeError


1

ডিক্ট = {"স্টেননেম": "আসস"} কীস = ডিক্ট.কিজ () তালিকার কীগুলির জন্য (কী): ডিক্ট [কী.ইপার ()] = 'নতুন মান' মুদ্রণ (স্ট্রিং (ডিক্ট))


0

রানটাইম ত্রুটির কারণ হ'ল আপনি যদি কোনও ডেটার কাঠামোর মাধ্যমে পুনরাবৃত্তি করতে পারবেন না তবে এর কাঠামোটি পুনরাবৃত্তির সময় পরিবর্তিত হচ্ছে।

আপনি যা সন্ধান করছেন তা অর্জনের একটি উপায় হ'ল আপনি যে কীগুলি সরাতে চান সেটি যুক্ত করতে তালিকাটি ব্যবহার করুন এবং তারপরে তালিকার মাধ্যমে পুনরাবৃত্তি করার সময় চিহ্নিত কীটি সরিয়ে ফেলতে অভিধানে পপ ফাংশন ব্যবহার করুন।

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

for i in d:
        if not d[i]:
                pop_list.append(i)

for x in pop_list:
        d.pop(x)
print (d)

0

পাইথন 3 অভিধানটি পুনরাবৃত্ত করার সময় মুছে ফেলার অনুমতি দেয় না (উপরের লুপের জন্য ব্যবহার করে)। বিভিন্ন বিকল্প আছে; একটি সহজ উপায় নিম্নলিখিত লাইন পরিবর্তন করা হয়

for i in x.keys():

সঙ্গে

for i in list(x)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.