পাইথন ডিকটি সংশোধন করা হচ্ছে যখন এটির পুনরাবৃত্তি হবে


87

ধরা যাক আমাদের কাছে পাইথন অভিধান রয়েছে dএবং আমরা এটির মতো পুনরাবৃত্তি করছি:

for k,v in d.iteritems():
    del d[f(k)] # remove some item
    d[g(k)] = v # add a new item

( fএবং gকেবল কয়েকটি ব্ল্যাক-বক্স রূপান্তর।

অন্য কথায়, আমরা আইটেমগুলি dব্যবহার করে এটির পুনরাবৃত্তি করার সময় যুক্ত / সরানোর চেষ্টা করি iteritems

এটি কি ভাল সংজ্ঞা দেওয়া হয়েছে? আপনার উত্তর সমর্থন করতে আপনি কিছু রেফারেন্স সরবরাহ করতে পারেন?

(এটি যদি ভেঙে যায় তবে কীভাবে এটি ঠিক করবেন এটি বেশ স্পষ্ট সুতরাং এটি আমার পরে থাকা কোণ নয়))




আমি এটি করার চেষ্টা করেছি এবং দেখে মনে হচ্ছে আপনি যদি প্রাথমিক ডিকের আকারটি অপরিবর্তিত রেখে দেন - যেমন কোনও কী /
মানগুলি সেগুলি

আমি একমত নই যে এই বিষয়টির সন্ধানকারী প্রত্যেকের জন্য (নিজেকে সহ) এটি "যদি এটি ভেঙে যায় তবে কীভাবে এটি ঠিক করা যায় এটি বেশ স্পষ্টভাবে স্পষ্ট" I এবং আমি আশা করি গ্রহণযোগ্য উত্তরটি কমপক্ষে এটিকে স্পর্শ করে।
অ্যালেক্স পিটারস

উত্তর:


54

পাইথন ডক পৃষ্ঠায় এটি স্পষ্টভাবে উল্লেখ করা হয়েছে ( পাইথন ২.7 এর জন্য ) এটি

iteritems()অভিধানে এন্ট্রি যোগ বা মুছে ফেলার সময় ব্যবহার RuntimeErrorকরা সমস্ত এন্ট্রিগুলিতে পুনরাবৃত্তি করতে বা ব্যর্থ হতে পারে।

একইভাবে পাইথন 3 এর জন্য

এটি একইরকম iter(d), d.iterkeys()এবং d.itervalues(), এবং আমি যতদূর বলব যে এটির জন্য রয়েছে for k, v in d.items():(আমি ঠিক কী করতে পারি তা মনে করতে পারছি না for, তবে বাস্তবায়ন ডেকে উঠলে আমি অবাক হব না iter(d))।


51
আমি খুব কোড স্নিপেট ব্যবহার করে এই মন্তব্য করে সম্প্রদায়ের স্বার্থে নিজেকে বিব্রত করব। আমি ভেবেছিলাম যেহেতু আমি রানটাইম এরির না পেয়েছি ভেবেছি সবকিছুই ভাল। এবং এটি ছিল, কিছু সময়ের জন্য। অ্যানালি রিটেনটিভ ইউনিট পরীক্ষাগুলি আমাকে থাম্বস আপ দিচ্ছিল এবং এটি প্রকাশিত হওয়ার পরেও এটি ভাল চলছে। তারপরে, আমি উদ্ভট আচরণ পেতে শুরু করি। যা ঘটছিল তা হ'ল অভিধানের আইটেমগুলি এড়িয়ে যাচ্ছিল এবং অভিধানের সমস্ত আইটেম স্ক্যান করা যাচ্ছিল না। বাচ্চারা, আমি আমার জীবনে যে ভুলগুলি করেছি তা থেকে শিখুন এবং কেবল না বলুন! ;)
অ্যালান ক্যাবেরা

4
আমি যদি বর্তমান কী-তে মান পরিবর্তন করি তবে (তবে কোনও কী যুক্ত করা বা মুছে ফেলা হচ্ছে না?) আমি কি সমস্যাগুলির মধ্যে দৌড়াতে পারি? আমি ইমামআগেইন করব যে এটির কোনও সমস্যা না হওয়া উচিত, তবে আমি জানতে চাই!
Gershy

@ জারশোমেস আমি কারও সম্পর্কে জানি না, তবে আপনার লুপ বডিটি মানটি ব্যবহার করা উচিত এবং এটি পরিবর্তনের প্রত্যাশা না করে আপনি এখনও মাইনফিল্ডে চলে যাচ্ছেন।
রাফাল সেন্ট-পিয়ের

4
d.items()পাইথন ২.7 এ নিরাপদ থাকা উচিত (পাইথন 3 এর সাথে গেমটি পরিবর্তিত হয়), যা এটি মূলত একটি অনুলিপি করে তোলে d, তাই আপনি কী পরিবর্তন করছেন তা পরিবর্তন করছেন না mod
পল দাম

এটিও সত্য কিনা তা জানতে আগ্রহী হবেviewitems()
jlh

51

অ্যালেক্স মার্টেলি এখানে এটি উপর ওজন ।

ধারকটি লুপ করার সময় পাত্রে পরিবর্তন করা নিরাপদ নয় (যেমন ডিক) eg সুতরাং del d[f(k)]নিরাপদ নাও হতে পারে। আপনি জানেন যে, কাজটি হ'ল d.items()(কনটেইনারটির একটি স্বতন্ত্র অনুলিপিটি লুপ করার জন্য) পরিবর্তে d.iteritems()(যা একই অন্তর্নিহিত ধারক ব্যবহার করে)।

ডিকের বিদ্যমান সূচকে মানটি সংশোধন করা ঠিক আছে তবে নতুন সূচকে (যেমন d[g(k)]=v) মান সন্নিবেশ করানো কাজ করবে না।


4
আমি মনে করি এটি আমার পক্ষে একটি মূল উত্তর। প্রচুর ব্যবহারের ক্ষেত্রে একটি প্রক্রিয়া সন্নিবেশ করানো এবং অন্য পরিষ্কার করার জিনিসগুলি থাকবে / সেগুলি মুছে ফেলা যাতে d.items () ব্যবহার করার পরামর্শ কার্যকর করে। পাইথন 3 সতর্কতা সহ্য করে না
ইজিটিগার

4
পাইথন 3 ক্যাভেট সম্পর্কে আরও তথ্য পিইপি 469 তে পাওয়া যাবে যেখানে উপরোক্ত পাইথন 2 ডিক পদ্ধতিগুলির অর্থগত সমতুল্য গণনা করা হয়েছে।
লিওনেল ব্রুকস 21

4
"ডিকের বিদ্যমান সূচকে মানটি সংশোধন করা ঠিক আছে" - আপনার কি এর জন্য একটি রেফারেন্স রয়েছে?
জনাথন রেইনহার্ট

4
@ জোনাথনরাইনহার্ট: না, এর জন্য আমার কাছে কোনও উল্লেখ নেই, তবে আমি পাইথনে এটি বেশ মানক বলে মনে করি। উদাহরণস্বরূপ, অ্যালেক্স মার্তেলি একটি পাইথন কোর বিকাশকারী এবং এখানে এর ব্যবহারের প্রদর্শন করে
আনটবু

27

আপনি এটি করতে পারবেন না, অন্তত সাথে d.iteritems()। আমি চেষ্টা করেছিলাম, এবং পাইথন ব্যর্থ হয়

RuntimeError: dictionary changed size during iteration

আপনি যদি পরিবর্তে এটি ব্যবহার করেন d.items(), তবে এটি কার্যকর হয়।

পাইথন 3- তে পাইথন ২-এর d.items()মতো অভিধানেরও একটি দর্শন is এটি পাইথন 3- d.iteritems()তে করতে পরিবর্তে ব্যবহার করুন d.copy().items()। এটি একইভাবে আমাদের অভিধানের অনুলিপিটি পুনর্বিবেচনার জন্য ডেটা কাঠামোর পরিবর্তন এড়াতে অভিধানের অনুলিপিটির মাধ্যমে পুনরাবৃত্তি করার অনুমতি দেবে।


4
আমি আমার উত্তরে পাইথন 3 যুক্ত করেছি।
murgatroid99

4
অবগতির জন্য, আক্ষরিক অনুবাদ (যেমন যেমন দ্বারা ব্যবহৃত 2to3) Py2 এর d.items()Py3 হয় list(d.items()), যদিও d.copy().items()তুলনীয় কার্যকারিতা সম্ভবত নেই।
সেরেন ল্যাভবার্গ

4
ডিক অবজেক্টটি যদি খুব বড় হয় তবে কী ডকপি ()। আইটেমস () কার্যকর হয়?
ড্রাগনফ্লাই

12

আমার কাছে নম্পি অ্যারে সমন্বিত একটি বিশাল অভিধান রয়েছে, সুতরাং @ মুরগাট্রয়েড 99 এর দ্বারা প্রস্তাবিত ডিক্ট কপি ()। কীগুলি () কার্যকর করা যায় নি (যদিও এটি কার্যকর)। পরিবর্তে, আমি কেবল কী_ভিউকে একটি তালিকায় রূপান্তর করেছি এবং এটি দুর্দান্ত কাজ করেছে (পাইথন ৩.৪ এ):

for item in list(dict_d.keys()):
    temp = dict_d.pop(item)
    dict_d['some_key'] = 1  # Some value

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


6

নিম্নলিখিত কোডটি দেখায় যে এটি ভালভাবে সংজ্ঞায়িত হয়নি:

def f(x):
    return x

def g(x):
    return x+1

def h(x):
    return x+10

try:
    d = {1:"a", 2:"b", 3:"c"}
    for k, v in d.iteritems():
        del d[f(k)]
        d[g(k)] = v+"x"
    print d
except Exception as e:
    print "Exception:", e

try:
    d = {1:"a", 2:"b", 3:"c"}
    for k, v in d.iteritems():
        del d[f(k)]
        d[h(k)] = v+"x"
    print d
except Exception as e:
    print "Exception:", e

প্রথম উদাহরণটি জি (কে) কল করে এবং একটি ব্যতিক্রম ছোঁড়ে (পুনরাবৃত্তির সময় অভিধান পরিবর্তিত আকার)।

দ্বিতীয় উদাহরণটি h (কে) কল করে এবং কোনও ব্যতিক্রম ছোঁড়ে না, তবে ফলাফলগুলি:

{21: 'axx', 22: 'bxx', 23: 'cxx'}

কোডটির দিকে তাকানো কোনটি ভুল বলে মনে হচ্ছে - আমি এমন কিছু আশা করতাম:

{11: 'ax', 12: 'bx', 13: 'cx'}

আপনি কেন আশা করতে পারেন তা আমি বুঝতে পারি {11: 'ax', 12: 'bx', 13: 'cx'}তবে 21,22,23 আপনাকে আসলে কী ঘটেছে তা সম্পর্কে ধারণা দেওয়া উচিত: আপনার লুপটি 1, 2, 3, 11, 12, 13 আইটেমগুলির মধ্য দিয়ে গেছে তবে দ্বিতীয়টি বেছে নিতে পারে নি আপনি ইতিমধ্যে পুনরাবৃত্তি করা আইটেমগুলির সামনে নতুন আইটেমগুলি ofোকানো হবে round h()ফিরে আসার জন্য পরিবর্তন করুন x+5এবং আপনি অন্য এক্স পাবেন: 'axxx'ইত্যাদি বা 'x + 3' এবং আপনি দুর্দান্ত পাবেন'axxxxx'
ডানকান

হ্যাঁ, আমার ভুলটি আমি ভয় করি - আপনার প্রত্যাশিত আউটপুটটি {11: 'ax', 12: 'bx', 13: 'cx'}আপনি যেমন বলেছিলেন, তাই আমি এটি সম্পর্কে আমার পোস্ট আপডেট করব। যেভাবেই হোক না কেন, এটি পরিষ্কারভাবে সংজ্ঞায়িত আচরণ নয়।
combatdave

1

আমি একই সমস্যা পেয়েছি এবং আমি এই সমস্যাটি সমাধান করার জন্য নিম্নলিখিত পদ্ধতি ব্যবহার করেছি।

পাইথন তালিকাটি পুনরাবৃত্তি হতে পারে এমনকি যদি আপনি এটির উপরে পুনরাবৃত্তি করার সময় সংশোধন করেন। সুতরাং নিম্নলিখিত কোডের জন্য এটি অনন্তকাল 1 টি মুদ্রণ করবে।

for i in list:
   list.append(1)
   print 1

সুতরাং তালিকা এবং ডিক সহযোগিতামূলকভাবে ব্যবহার করে আপনি এই সমস্যাটি সমাধান করতে পারেন।

d_list=[]
 d_dict = {} 
 for k in d_list:
    if d_dict[k] is not -1:
       d_dict[f(k)] = -1 # rather than deleting it mark it with -1 or other value to specify that it will be not considered further(deleted)
       d_dict[g(k)] = v # add a new item 
       d_list.append(g(k))

আমি নিশ্চিত নই যে পুনরাবৃত্তির সময় কোনও তালিকা পরিবর্তন করা নিরাপদ কিনা (যদিও এটি কিছু ক্ষেত্রে কাজ করতে পারে)। উদাহরণস্বরূপ এই প্রশ্নটি দেখুন ...
রোমান

@ রোমান আপনি যদি কোনও তালিকার উপাদানগুলি মুছতে চান তবে আপনি নিরাপদে বিপরীত ক্রমে এটি পুনরাবৃত্তি করতে পারেন, যেহেতু সাধারণ ক্রমে পরবর্তী উপাদানটির সূচক মুছে ফেলার পরে পরিবর্তিত হবে। এই উদাহরণটি দেখুন।
mbomb007

1

পাইথন 3 আপনার উচিত:

prefix = 'item_'
t = {'f1': 'ffw', 'f2': 'fca'}
t2 = dict() 
for k,v in t.items():
    t2[k] = prefix + v

বা ব্যবহার করুন:

t2 = t1.copy()

আপনার কখনই মূল অভিধানটি পরিবর্তন করা উচিত নয়, এটি বিভ্রান্তির পাশাপাশি সম্ভাব্য বাগগুলি বা রানটাইমআরিয়ার দিকে পরিচালিত করে। আপনি কেবল নতুন কী নামের সাথে অভিধানে যুক্ত না হয়ে থাকেন।


0

আজ আমার অনুরূপ ব্যবহারের ঘটনা ঘটেছে, তবে লুপের শুরুতে অভিধানের কীগুলি কেবলমাত্রায়িত করার পরিবর্তে ডেকের পুনরাবৃত্তিকে প্রভাবিত করার জন্য ডিকের পরিবর্তনগুলি চেয়েছিলাম, যা একটি আদেশযুক্ত ডিক ছিল।

আমি নীচের রুটিনটি তৈরি করে শেষ করেছি, যা জারাকো.িটোরটোলেও পাওয়া যাবে :

def _mutable_iter(dict):
    """
    Iterate over items in the dict, yielding the first one, but allowing
    it to be mutated during the process.
    >>> d = dict(a=1)
    >>> it = _mutable_iter(d)
    >>> next(it)
    ('a', 1)
    >>> d
    {}
    >>> d.update(b=2)
    >>> list(it)
    [('b', 2)]
    """
    while dict:
        prev_key = next(iter(dict))
        yield prev_key, dict.pop(prev_key)

ডকস্ট্রিং এর ব্যবহারের চিত্র তুলে ধরেছে। d.iteritems()পছন্দসই প্রভাব পেতে এই ফাংশনটি উপরের স্থানে ব্যবহার করা যেতে পারে ।

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