লুপের সময় তালিকার এন্ট্রিগুলি কীভাবে সংশোধন করবেন?


178

এখন আমি জানি যে পুনরাবৃত্তীয় লুপিংয়ের সময় তালিকাটি পরিবর্তন করা নিরাপদ নয়। তবে, ধরুন আমার কাছে স্ট্রিংগুলির একটি তালিকা রয়েছে এবং আমি নিজেই স্ট্রিংগুলি ছাঁটাই করতে চাই। পরিবর্তনীয় মানগুলি প্রতিস্থাপনকে সংশোধনী হিসাবে গণ্য করা হয়?


20
একটি স্ট্রিং কোনও পরিবর্তনীয় মান তৈরি করে না।
user470379

4
@ user470379: তালিকার উপাদানগুলি পরিবর্তনযোগ্য কিনা তা সুরক্ষিত কিনা তা লুপ করার সময় তারা যে তালিকায় রয়েছেন তা পরিবর্তন করতে হবে কিনা সেটির সাথে প্রাসঙ্গিক নয়।
মার্টিনো

উত্তর:


144

এটি দুর্বল রূপ হিসাবে বিবেচিত। স্লাইস অ্যাসাইনমেন্ট সহ পরিবর্তে একটি তালিকা বোধগম্য ব্যবহার করুন যদি আপনার তালিকার বিদ্যমান রেফারেন্সগুলি ধরে রাখতে হয়।

a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)

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

11
কেন আমরা খ = এ নিয়োগ করব?
ভিজ্রন্ড

9
@ ভিগরন্ড: সুতরাং যখন print bবিবৃতিটি কার্যকর করা হবে তখন আপনি বলতে পারবেন aপ্রতিস্থাপনের পরিবর্তে জায়গায় জায়গায় পরিবর্তন করা হয়েছে কিনা । আরেকটি সম্ভাবনা হ'ল print b is aতারা উভয় এখনও একই বস্তুর উল্লেখ করে কিনা তা দেখার জন্য।
মার্টিনো

12
কেন একটি [:] = এবং শুধু a = নয়?
kdubs

10
@ কেডাবস: "... তালিকার বিদ্যমান রেফারেন্সগুলি বজায় রাখার প্রয়োজন হলে স্লাইস অ্যাসাইনমেন্ট সহ" "
ইগনাসিও ওয়াজকেজ-

162

যেহেতু নীচের লুপটি কেবল ইতিমধ্যে দেখা উপাদানগুলিকে সংশোধন করে, তাই এটি গ্রহণযোগ্য হিসাবে বিবেচিত হবে:

a = ['a',' b', 'c ', ' d ']

for i, s in enumerate(a):
    a[i] = s.strip()

print(a) # -> ['a', 'b', 'c', 'd']

যা থেকে পৃথক:

a[:] = [s.strip() for s in a]

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

সতর্কতা: যদিও আপনি এন্ট্রিগুলিকে এভাবে পরিবর্তন করতে পারেন তবে listসমস্যার মুখোমুখি হওয়ার ঝুঁকি না রেখে আপনি আইটেমের সংখ্যা পরিবর্তন করতে পারবেন না ।

এখানে আমি কী বোঝাতে চাইছি তার একটি উদাহরণ এখানে — বিন্দুটি মুছে ফেলা হচ্ছে point বিন্দু থেকে সূচীকরণ:

b = ['a', ' b', 'c ', ' d ']

for i, s in enumerate(b):
    if s.strip() != b[i]:  # leading or trailing whitespace?
        del b[i]

print(b)  # -> ['a', 'c ']  # WRONG!

(ফলাফলটি ভুল কারণ এটি থাকা সমস্ত আইটেম মুছে ফেলেনি))

হালনাগাদ

যেহেতু এটি একটি মোটামুটি জনপ্রিয় উত্তর, কার্যকরভাবে কীভাবে "ইন-প্লেস" এন্ট্রিগুলি মুছে ফেলা যায় (যদিও এটি ঠিক তেমন প্রশ্ন নয়):

b = ['a',' b', 'c ', ' d ']

b[:] = [entry for entry in b if entry.strip() == entry]

print(b)  # -> ['a']  # CORRECT

3
পাইথন for i in aযদিও সিনট্যাক্সে পৃথক উপাদানগুলির কেবল একটি অনুলিপি তৈরি করে ? এটি অত্যন্ত বিপরীতমুখী, অন্য ভাষা থেকে আপাতদৃষ্টিতে পৃথক এবং আমার কোডটিতে ত্রুটি রয়েছে যার ফলে আমাকে দীর্ঘ সময়ের জন্য ডিবাগ করতে হয়েছিল। পাইথন টিউটোরিয়াল এমনকি এটি উল্লেখ করে না। যদিও এর কিছু কারণ থাকতে হবে?
xji

1
@ জিক্সিয়াং: এটি অনুলিপি তৈরি করে না। এটি কেবল ক্রমাগত উপাদানগুলিকে লুপ ভেরিয়েবলের নাম বা জিনিসটির পুনরাবৃত্তি হওয়ার জন্য মূল্য নির্ধারণ করে।
মার্টিনিউ

1
তবে, যখন আপনার দরকার নেই তখন একই লাইনে একই বস্তুর জন্য দুটি নাম ( a[i]এবং s) কেন ব্যবহার করবেন? আমি বরং অনেক কিছু করতাম a[i] = a[i].strip()
নবীন

3
@ নাভিন: কারণ a[i] = s.strip()কেবল একটি সূচিকরণ কাজ করে।
মার্টিনো

1
@ মার্টিনেউ enumerate(b)প্রতিটি পুনরাবৃত্তির উপর একটি সূচীকরণ অপারেশন করে এবং আপনি এর সাথে আরও একটি করছেন a[i] =। এএএআইএফকি পাইপনে এই লুপটি কার্যকর করা অসম্ভব প্রতি লুপ পুনরাবৃত্তির জন্য কেবল 1 টি সূচীকরণ অপারেশন দিয়ে :(
নবীন

18

লুপ বৈকল্পিকের জন্য আরও একটি, আমার কাছে গণনাযুক্ত () এর চেয়ে পরিষ্কার মনে হচ্ছে:

for idx in range(len(list)):
    list[idx]=... # set a new value
    # some other code which doesn't let you use a list comprehension

19
অনেকে range(len(list))পাইথনের মতো কোড গন্ধের মতো কিছু ব্যবহার করা বিবেচনা করে ।
মার্টিনো

2
@ রিশিন: যেহেতু enumerateএকটি জেনারেটর তাই এটি কোনও তালিকা তৈরি করে না t টুপলস, তালিকার মধ্য দিয়ে পুনরাবৃত্তি হওয়ার সাথে সাথে এটি একবারে তাদের তৈরি করে। ধীরে ধীরে কোনটি বলার একমাত্র উপায় হ'ল timeit
মার্টিনো

3
@ মার্টিনো কোডটি খুব সুন্দর হতে পারে না, তবে অনুযায়ী timeit enumerateধীর
রিশিন

2
@ রিশিন: আপনার বেঞ্চমার্কিং কোডটি পুরোপুরি বৈধ নয় কারণ এটি প্রদত্ত সূচকে তালিকার মানটি পুনরুদ্ধারের প্রয়োজনীয়তার বিষয়টি বিবেচনায় নেয় না - যা এই উত্তরেও প্রদর্শিত হয় না।
মার্টিনো

4
@ রিশিন: আপনার তুলনা ঠিক সেই কারণেই অবৈধ। এটি বিচ্ছিন্নভাবে লুপিং ওভারহেড পরিমাপ করছে। সম্পূর্ণ লুপটি কার্যকর করতে যে সময় লাগে তা পরিমাপ করতে হবে কারণ সম্ভবত কোনও উপায়ে লুপিংয়ের অভ্যন্তরে কোডটিতে প্রদত্ত সুবিধার ফলে কোনও ওভারহেডের পার্থক্য হ্রাস পেতে পারে - অন্যথায় আপনি আপেলের সাথে তুলনা করছেন না আপেল।
মার্টিনো

11

তালিকার পুনরাবৃত্তি করার সময় প্রতিটি উপাদানকে সংশোধন করা ভাল, যতক্ষণ না আপনি তালিকাতে উপাদানগুলি যোগ / সরান না।

আপনি তালিকা বোঝার ব্যবহার করতে পারেন:

l = ['a', ' list', 'of ', ' string ']
l = [item.strip() for item in l]

বা কেবল C-styleলুপের জন্য করুন:

for index, item in enumerate(l):
    l[index] = item.strip()

4

না আপনি তালিকার "সামগ্রী" পরিবর্তন করতে পারবেন না, যদি আপনি সেইভাবে স্ট্রিংগুলিকে পরিবর্তন করতে পারেন ate কিন্তু পাইথনে এগুলি পরিবর্তনীয় নয়। যে কোনও স্ট্রিং অপারেশন একটি নতুন স্ট্রিং দেয়।

আপনি যদি জানতেন এমন সামগ্রীর একটি তালিকা যদি আপনি পরিবর্তন করতে পারেন তবে আপনি যতক্ষণ তালিকার প্রকৃত বিষয়বস্তু পরিবর্তন না করে আপনি এটি করতে পারতেন।

এইভাবে আপনাকে কোনও ধরণের মানচিত্র তৈরি করতে হবে। আপনি যদি কোনও জেনারেটর এক্সপ্রেশন ব্যবহার করেন তবে পুনরাবৃত্তি করার সাথে সাথে [অপারেশন] সম্পন্ন হবে এবং আপনি স্মৃতি সংরক্ষণ করবেন।


4

আপনি এর মতো কিছু করতে পারেন:

a = [1,2,3,4,5]
b = [i**2 for i in a]

আপনার পক্ষে তালিকার অভ্যন্তরে লুপ করা সহজ করার জন্য এটিকে একটি তালিকা বোঝার বলা হয় called


3

জেমশিত ইস্কেন্দেরোভ এবং ইগনাসিও ওয়াজকেজ-আব্রামসের দেওয়া উত্তরটি সত্যিই ভাল। এটি এই উদাহরণের সাথে আরও চিত্রিত করা যেতে পারে: এটি কল্পনা করুন

ক) দুটি ভেক্টর সহ একটি তালিকা আপনাকে দেওয়া হয়েছে;

খ) আপনি তালিকাটি অতিক্রম করতে এবং অ্যারের প্রত্যেকের ক্রমের বিপরীত করতে চান

বলুন আপনার আছে

v = np.array([1, 2,3,4])
b = np.array([3,4,6])

for i in [v, b]:
    i = i[::-1]   # this command does not reverse the string

print([v,b])

তুমি পাবে

[array([1, 2, 3, 4]), array([3, 4, 6])]

অন্যদিকে, আপনি যদি

v = np.array([1, 2,3,4])
b = np.array([3,4,6])

for i in [v, b]:
   i[:] = i[::-1]   # this command reverses the string

print([v,b])

ফলাফল হলো

[array([4, 3, 2, 1]), array([6, 4, 3])]

1

আপনার স্ট্রিংটি কী কী স্ট্রিংগুলি অপসারণ করবেন তা স্থির করার মানদণ্ডটি কী তা পরিষ্কার নয় তবে আপনি যদি মুছে ফেলতে চান এমন স্ট্রিংগুলির একটি তালিকা বা তৈরি করতে পারেন তবে আপনি নিম্নলিখিতটি করতে পারেন:

my_strings = ['a','b','c','d','e']
undesirable_strings = ['b','d']
for undesirable_string in undesirable_strings:
    for i in range(my_strings.count(undesirable_string)):
        my_strings.remove(undesirable_string)

যা আমার_স্ট্রিংগুলিকে ['ক', 'সি', 'ই'] তে পরিবর্তন করে


0

সংক্ষেপে, একই তালিকা পুনরাবৃত্তি করার সময় তালিকায় পরিবর্তন করতে।

list[:] = ["Modify the list" for each_element in list "Condition Check"]

উদাহরণ:

list[:] = [list.remove(each_element) for each_element in list if each_element in ["data1", "data2"]]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.