পুনরাবৃত্তি করার সময় তালিকা থেকে আইটেমগুলি কীভাবে সরিয়ে ফেলা যায়?


934

আমি পাইথনের টিপলগুলির তালিকার উপরে পুনরাবৃত্তি করছি এবং তারা যদি কিছু মানদণ্ড পূরণ করে তবে সেগুলি সরিয়ে দেওয়ার চেষ্টা করছি।

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

এর জায়গায় আমার কী ব্যবহার করা উচিত code_to_remove_tup? এই ফ্যাশনে আইটেমটি কীভাবে সরিয়ে নেওয়া যায় তা আমি বুঝতে পারি না।


এই পৃষ্ঠার বেশিরভাগ উত্তর সত্যই ব্যাখ্যা করে না যে তালিকার পুনরাবৃত্তির সময় কেন উপাদানগুলি অপসারণ করা বিস্ময়কর ফলাফল প্রকাশ করে, তবে এই প্রশ্নের গ্রহণযোগ্য উত্তরটি দেয় এবং সম্ভবত প্রথমবারের মতো এই সমস্যাটির মুখোমুখি হওয়া নতুনদের জন্য এটি আরও ভাল দ্বিগুণ।
ggorlen

উত্তর:


827

আপনি কেবলমাত্র উপাদানগুলি অপসারণ করতে চান না সেগুলি সহ একটি নতুন তালিকা তৈরি করতে আপনি একটি তালিকা বোধগম্যতা ব্যবহার করতে পারেন:

somelist = [x for x in somelist if not determine(x)]

অথবা, স্লাইসটি বরাদ্দ করে আপনি somelist[:]বিদ্যমান তালিকাকে কেবল নিজের পছন্দসই আইটেমগুলিতে রাখতে পরিবর্তন করতে পারেন:

somelist[:] = [x for x in somelist if not determine(x)]

somelistপরিবর্তনগুলি প্রতিফলিত করার জন্য অন্যান্য উল্লেখের প্রয়োজন থাকলে এই পদ্ধতিকে কার্যকর হতে পারে ।

বোঝার পরিবর্তে, আপনিও ব্যবহার করতে পারেন itertools। পাইথন 2 এ:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

বা পাইথন 3 এ:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)

স্পষ্টতার স্বার্থে এবং যারা [:]স্বীকৃতি হ্যাকিশ বা ফাজি ব্যবহারটি খুঁজে পান তাদের জন্য এখানে আরও স্পষ্ট বিকল্প রয়েছে alternative তাত্ত্বিকভাবে, এটি স্থান ও সময়ের সাথে সম্পর্কিত ওপরের এক-লাইনারের চেয়ে একই সম্পাদন করা উচিত।

temp = []
while somelist:
    x = somelist.pop()
    if not determine(x):
        temp.append(x)
while temp:
    somelist.append(templist.pop())

এটি অন্যান্য ভাষাগুলিতেও কাজ করে যার মধ্যে পাইথন তালিকাগুলির প্রতিস্থাপন আইটেমগুলির ক্ষমতা ন্যূনতম পরিবর্তন সহ। উদাহরণস্বরূপ, Falseপাইথনের মতো সমস্ত ভাষা খালি তালিকা নিক্ষেপ করে না। আপনি while somelist:আরও সুস্পষ্ট কিছু জন্য বিকল্প করতে পারেন while len(somelist) > 0:


4
আপনি কী দ্রুত এটি তৈরি করতে পারবেন যদি আপনি জানেন যে কেবলমাত্র কয়েকটি মুছে ফেলা হবে, অর্থাৎ কেবল সেগুলি মুছুন এবং অন্যদের পুনরায় লেখার পরিবর্তে অন্য জায়গায় রেখে দিন?
হাইব্যান্ডউইথথ

20
আমার তালিকাটি বিশাল এবং অনুলিপি তৈরি করতে না পারলে কী হয়?
jpcgt

15
@jpcgt আপনার ব্যবহার করা উচিত somelist[:] = (x for x in somelist if determine(x))এমন জেনারেটর তৈরি করবে যা কোনও অপ্রয়োজনীয় অনুলিপি তৈরি করতে পারে না।
রোস্টিস্লাভ কন্ড্রাটেনকো

8
@ রোস্টিস্লাভকন্ড্রাটেনকো: list_ass_slice()ফাংশন যা অভ্যন্তরীণভাবে somelist[:]=কলগুলি কার্যকর করে PySequence_Fast()। এই ফাংশনটি সর্বদা একটি তালিকা ফেরত দেয় যেমন, @ অ্যালেক্স মার্তেলির সমাধান যা ইতিমধ্যে জেনারেটরের পরিবর্তে একটি তালিকা ব্যবহার করে সম্ভবত সবচেয়ে কার্যকর
jfs

6
আপনি তালিকা এবং তালিকা ক্লোন দয়া করে তালিকাটি বোঝার ক্ষমতা নির্ধারণের মধ্যে পার্থক্যগুলি কী তা বোঝানোর যত্ন নেবেন? মূল তালিকাটি somelistউভয় পদ্ধতিতে পরিবর্তিত হবে না?
বোভেন লিউ

589

তালিকার বোধগম্যতার জন্য প্রস্তাবিত উত্তরগুলি সম্পূর্ণ সঠিক - তারা সম্পূর্ণ নতুন তালিকা তৈরি করে এবং তারপরে এটিকে পুরানো তালিকা হিসাবে একই নাম দেয়, তারা পুরানো তালিকাটি জায়গায় পরিবর্তন করে না। @ লেনার্টের পরামর্শ অনুসারে আপনি যা বেছে বেছে অপসারণের মাধ্যমে করছেন তা থেকে আলাদা - এটি দ্রুত, তবে যদি আপনার তালিকাটি একাধিক রেফারেন্সের মাধ্যমে অ্যাক্সেস করা হয় তবে আপনি যদি কেবলমাত্র একটি উল্লেখ খুঁজে বের করছেন এবং তালিকার অবজেক্টটি পরিবর্তন করছেন না তা এই সত্য that নিজেই সূক্ষ্ম, বিপর্যয়মূলক বাগ বাড়ে।

ভাগ্যক্রমে, তালিকা বোধগতির গতি এবং স্থান পরিবর্তনের প্রয়োজনীয় শব্দার্থক উভয়ই পাওয়া অত্যন্ত সহজ - কেবল কোড:

somelist[:] = [tup for tup in somelist if determine(tup)]

অন্যান্য উত্তরের সাথে সূক্ষ্ম পার্থক্যটি নোট করুন: এটি একটি খালি নামকে বরাদ্দ দিচ্ছে না - এটি একটি তালিকা স্লাইসকে অর্পণ করছে যা কেবলমাত্র পুরো তালিকা হিসাবে ঘটে থাকে, যার ফলে কেবলমাত্র একটি রেফারেন্সের পুনর্বিবেচনা না করে একই পাইথন তালিকার অবজেক্টের মধ্যে তালিকার সামগ্রীগুলি প্রতিস্থাপন করা হয় cing (পূর্ববর্তী তালিকা থেকে নতুন তালিকার অবজেক্টে) অন্যান্য উত্তরের মতো like


1
আমি কীভাবে একটি ডিকের সাথে একই টুকরো টুকরো টুকিটাকি কাজ করব? পাইথন 2.6 এ?
পলএমসিজি

11
@ পল: যেহেতু পাতাগুলি বিন্যস্ত থাকে না, তাই টুকরোটি ডাইকের পক্ষে অর্থহীন। আপনার চান অভি সামগ্রীগুলি প্রতিস্থাপন করতে পারেন aঅভি বিষয়বস্তু দ্বারা b, ব্যবহার a.clear(); a.update(b)
সোভেন মারনাচ

1
ভেরিয়েবল কী কারণে বাগের কারণ বোঝায় তা প্রতিস্থাপন করে কেন কোনও একটি রেফারেন্স 'পুনর্বারণ' করতে পারেন? দেখে মনে হচ্ছে এটি কেবল একক থ্রেডযুক্ত নয়, বহু-থ্রেডযুক্ত অ্যাপ্লিকেশনগুলিতে সম্ভাব্য সমস্যা হবে।
ডেরেক ডাহমার 22 ই

59
@ ডেরেক x = ['foo','bar','baz']; y = x; x = [item for item in x if determine(item)];এটি xতালিকা বোঝার ফলাফলটিকে পুনরায় স্বাক্ষর করে , তবে yএখনও মূল তালিকাটিকে বোঝায় ['foo','bar','baz']। যদি আপনি প্রত্যাশিত হন xএবং yএকই তালিকার উল্লেখ করেন তবে আপনি বাগগুলি প্রবর্তন করতে পারেন। আপনি সম্পূর্ণ তালিকা একটি ফালি থেকে বরাদ্দ, আলেক্স শো হিসাবে এই রোধ, এবং আমি এখানে দেন: x = ["foo","bar","baz"]; y = x; x[:] = [item for item in x if determine(item)];। তালিকাটি জায়গায় পরিবর্তিত হয়েছে। তালিকার সমস্ত তথ্যসূত্র (উভয় xএবং yএখানে) নতুন তালিকাকে উল্লেখ করে তা নিশ্চিত করে।
স্টিভেন টি। স্নাইডার

প্রকৃতপক্ষে, filterফাংশনটি ব্যবহার করে একটি নতুন তালিকা তৈরি হয়, উপাদানগুলিকে জায়গায় পরিবর্তন করে না ... কেবলolist[:] = [i for i in olist if not dislike(i)]
জন স্ট্রড

302

আপনাকে তালিকার একটি অনুলিপি গ্রহণ করতে হবে এবং প্রথমে এটি পুনরুক্ত করতে হবে, বা যা অপ্রত্যাশিত ফলাফল হতে পারে তার সাথে পুনরাবৃত্তি ব্যর্থ হবে।

উদাহরণস্বরূপ (কী ধরণের তালিকার উপর নির্ভর করে):

for tup in somelist[:]:
    etc....

একটি উদাহরণ:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]

13
@ জেন কারণ তালিকার অনুলিপিটির মধ্য দিয়ে দ্বিতীয়টি পুনরাবৃত্তি করে। সুতরাং আপনি যখন মূল তালিকাটি সংশোধন করেন, আপনি যে অনুলিপিটি পুনরাবৃত্তি করে তা পরিবর্তন করেন না।
লেনার্ট রেজেব্রো

3
তালিকার তুলনায় কিছু তালিকা তৈরির ক্ষেত্রে [:] আরও ভাল কি?
মারিউজ জামরো

3
list(somelist)পুনরাবৃত্তিযোগ্যকে তালিকায় রূপান্তর করবে। somelist[:]স্লাইসিং সমর্থন করে এমন একটি সামগ্রীর অনুলিপি তৈরি করে। সুতরাং তারা অগত্যা একই জিনিস না। এই ক্ষেত্রে আমি somelistঅবজেক্টটির একটি অনুলিপি তৈরি করতে চাই , তাই আমি ব্যবহার করি[:]
লেনার্ট রেজেব্রো

33
এটি পড়ার জন্য যে কেউ নোট করুন, এটি তালিকার জন্য খুব ধীর। remove()প্রতিটি পুনরাবৃত্তির জন্য পুরো তালিকায় যেতে হবে, তাই এটি চিরতরে নেবে।
ভাইরায়েল

7
মাত্র এক ডজন আইটেমের তালিকাগুলির ক্ষেত্রে বিগ ও টাইম কোনও বিষয় নয়। ভবিষ্যতের প্রোগ্রামারদের বোঝার জন্য প্রায়শই পরিষ্কার এবং সহজ পারফরম্যান্সের চেয়ে অনেক বেশি মূল্যবান।
স্টিভ

127
for i in range(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

আপনার পিছন দিকে যেতে হবে অন্যথায় এটি যে গাছের ডালে বসে আছেন তা বন্ধ করার মতো :-)

পাইথন 2 ব্যবহারকারী: প্রতিস্থাপন rangeদ্বারা xrangeএকটি হার্ডকোডেড তালিকা তৈরি এড়াতে


13
পাইথন সাম্প্রতিক সংস্করণে, আপনি ব্যবহার দ্বারা আরও বেশি পরিচ্ছন্ন এটা করতে পারেন reversed()builtin
ncoghlan

16
বিপরীত () একটি নতুন তালিকা তৈরি করে না, সরবরাহিত ক্রমের উপরে এটি একটি বিপরীত পুনরুক্তি তৈরি করে। গণনা করা () এর মতো, আপনাকে এটিকে তালিকা থেকে বের করতে হবে (আসলে) এটি থেকে একটি তালিকা পেতে get আপনার চিন্তা করা যেতে পারে সাজানো (), যা করে একটি নতুন তালিকা প্রত্যেক সময় তৈরি করুন (এটি আছে, তাই এটি তা বাছাই করতে পারেন)।
এনকোঘ্লান

1
@ মরিস কারণ একটি পুনরাবৃত্তি প্রদান করে enumerateএবং reversedএকটি অনুক্রম প্রত্যাশা করে। আমি মনে করি আপনি reversed(list(enumerate(somelist)))যদি মেমরিতে অতিরিক্ত তালিকা তৈরি করতে আপত্তি না করেন তবে আপনি এটি করতে পারেন।
ড্রভিকো

2
এটি অ্যারেগুলির জন্য ও (এন * এম), আপনি বড় তালিকা থেকে অনেকগুলি আইটেম সরিয়ে ফেললে এটি খুব ধীর হয় slow সুতরাং প্রস্তাবিত নয়।
স্যাম ওয়াটকিন্স

2
@ সামাওয়াটকিনস হ্যাঁ, আপনি যখন খুব বড় অ্যারে থেকে কয়েক উপাদানকে সরিয়ে দিচ্ছেন তখন এই উত্তরটি। মেমরির ব্যবহার কম তবে এটি mধীর হতে পারে ।
নবীন

52

অফিসিয়াল পাইথন 2 টিউটোরিয়াল 4.2। "বিবৃতি জন্য"

https://docs.python.org/2/tutorial/controlflow.html#for-statements

ডক্সের এই অংশটি এটি পরিষ্কার করে দিয়েছে:

  • এটি পরিবর্তন করতে আপনার পুনরাবৃত্ত তালিকার একটি অনুলিপি তৈরি করতে হবে
  • এটি করার এক উপায় হ'ল স্লাইস স্বরলিপি দিয়ে [:]

লুপের অভ্যন্তরে যখন আপনি পুনরাবৃত্তি করছেন তার ক্রমটি সংশোধন করার প্রয়োজন হয় (উদাহরণস্বরূপ নির্বাচিত আইটেমগুলি নকল করতে), আপনাকে প্রথমে একটি অনুলিপি তৈরি করার পরামর্শ দেওয়া হয়। সিকোয়েন্সের উপরে আইট্রেট করা স্পষ্টতই একটি অনুলিপি তৈরি করে না। স্লাইস নোটেশন এটি বিশেষত সুবিধাজনক করে তুলেছে:

>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

পাইথন 2 ডকুমেন্টেশন 7.3। "বিবৃতি জন্য"

https://docs.python.org/2/reference/compound_stmts.html#for

দস্তাবেজের এই অংশটি আবার বলেছে যে আপনাকে একটি অনুলিপি তৈরি করতে হবে, এবং প্রকৃত অপসারণের উদাহরণ দেয়:

দ্রষ্টব্য: ক্রমটি লুপ দ্বারা সংশোধন করা হচ্ছে যখন একটি সূক্ষ্মতা আছে (এটি কেবল পরিবর্তনীয় ক্রম, অর্থাৎ তালিকার জন্যই ঘটতে পারে)। কোন আইটেমটি পরবর্তী ব্যবহৃত হয় তার উপর নজর রাখার জন্য একটি অভ্যন্তরীণ কাউন্টার ব্যবহার করা হয় এবং প্রতিটি পুনরাবৃত্তিতে এটি বাড়ানো হয়। এই কাউন্টারটি ক্রমের দৈর্ঘ্যে পৌঁছে গেলে লুপটি সমাপ্ত হয়। এর অর্থ হ'ল স্যুট যদি সিকোয়েন্স থেকে বর্তমান (বা পূর্ববর্তী) আইটেমটি মুছে ফেলে তবে পরবর্তী আইটেমটি এড়িয়ে যাবে (যেহেতু এটি বর্তমান আইটেমটির সূচি পেয়েছে যা ইতিমধ্যে চিকিত্সা করা হয়েছে)। তেমনি, স্যুট যদি বর্তমান আইটেমটির আগে ক্রমটিতে কোনও আইটেম সন্নিবেশ করায়, বর্তমান আইটেমটি পরের বার লুপের মাধ্যমে আবার চিকিত্সা করা হবে। এর ফলে বাজে বাগগুলি হতে পারে যা পুরো ক্রমটির টুকরো ব্যবহার করে অস্থায়ী অনুলিপি তৈরি করে এড়ানো যায়, যেমন,

for x in a[:]:
    if x < 0: a.remove(x)

তবে, আমি এই প্রয়োগের সাথে একমত নই, যেহেতু পুরো তালিকাটি.remove() পুনরাবৃত্তি করতে হবে মানটি খুঁজে পেতে করতে হবে।

সেরা workaround

উভয় ক্ষেত্রেই:

  • স্ক্র্যাচ থেকে একটি নতুন অ্যারে শুরু করুন, এবং .append()শেষে: https://stackoverflow.com/a/1207460/895245

    এই সময় দক্ষ, তবে কম স্থান দক্ষ কারণ এটি পুনরাবৃত্তির সময় অ্যারের একটি অনুলিপি রাখে।

  • delএকটি সূচক সহ ব্যবহার করুন : https://stackoverflow.com/a/1207485/895245

    এটি অ্যারে অনুলিপি বিতরণ করায় এটি আরও কার্যকর স্থান, তবে এটি কম সময় সাশ্রয়ী কারণ সিপিথন তালিকাগুলি গতিশীল অ্যারেগুলির সাথে প্রয়োগ করা হয়

    এর অর্থ এই যে আইটেম অপসারণের জন্য নিম্নলিখিত সমস্ত আইটেমগুলি একের পর এক স্থানান্তরিত করা দরকার যা ও (এন)।

সাধারণত আপনি কেবলমাত্র .append()ডিফল্টরূপে দ্রুত বিকল্পের দিকে যেতে চান যদি না স্মৃতিশক্তি বড় উদ্বেগ না থাকে।

পাইথন এটি আরও ভাল করতে পারে?

দেখে মনে হচ্ছে এই নির্দিষ্ট পাইথন এপিআই উন্নত করা যেতে পারে। এটির সাথে তুলনা করুন, উদাহরণস্বরূপ:

উভয়ই এটি স্ফটিক স্পষ্ট করে দেয় যে আপনি পুনরাবৃত্তকারী ছাড়া নিজেই কোনও তালিকা পুনরাবৃত্তি করতে পারবেন না এবং তালিকাটি অনুলিপি না করেই আপনাকে তা করার কার্যকর উপায় সরবরাহ করে।

সম্ভবত অন্তর্নিহিত যুক্তিটি হ'ল পাইথন তালিকাগুলি ডায়নামিক অ্যারে ব্যাকড হিসাবে বিবেচিত হয়, এবং সেইজন্য যে কোনও ধরণের অপসারণ যেকোনোভাবেই সময় অদক্ষ হয়ে উঠবে, অন্যদিকে জাভা উভয়েরই একটি সুন্দর ইন্টারফেস স্তরক্রম ArrayListএবং এর LinkedListবাস্তবায়ন রয়েছে ListIterator

পাইথন স্টাডলিবের মধ্যে স্পষ্টত লিঙ্কযুক্ত তালিকার प्रकार নেই বলে মনে হচ্ছে: পাইথন লিঙ্কড তালিকান


48

এই জাতীয় উদাহরণের জন্য আপনার সেরা পদ্ধতির তালিকা বোধগম্যতা হবে

somelist = [tup for tup in somelist if determine(tup)]

আপনি যখন কোনও determineফাংশন কল করার চেয়ে আরও জটিল কিছু করছেন সেখানে আমি একটি নতুন তালিকা তৈরি করা এবং আমার যেতে যেতে কেবল এতে যুক্ত করা পছন্দ করি। উদাহরণ স্বরূপ

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

removeনীচের উত্তরগুলির মধ্যে একটিতে বর্ণিত হিসাবে ব্যবহার করে তালিকাটি অনুলিপি করা আপনার কোডকে কিছুটা পরিচ্ছন্ন দেখায়। আপনার অবশ্যই অত্যন্ত বৃহত তালিকার জন্য এটি করা উচিত নয়, কারণ এতে প্রথমে পুরো তালিকাটি অনুলিপি করা এবং O(n) removeপ্রতিটি উপাদানকে অপসারণের জন্য একটি ক্রিয়াকলাপ অন্তর্ভুক্ত করা হয়, এটি একটি O(n^2)অ্যালগরিদম করে।

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

37

যাঁরা কার্যকরী প্রোগ্রামিং পছন্দ করেন তাদের জন্য:

somelist[:] = filter(lambda tup: not determine(tup), somelist)

অথবা

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))

1. তালিকার বোধগম্যতা এবং জেনারেটর এক্সপ্রেশন হাস্কেল, একটি খাঁটি কার্যকরী ভাষা থেকে ধার করা হয়েছে; এগুলি ঠিক তেমনি কার্যকরী filterএবং আরও পাইথোনিক। ২. যদি আপনার lambdaব্যবহার করতে হয় mapবা প্রয়োজন হয় filterতবে তালিকাটি কমপ বা জেনেক্সপ্রাইস সর্বদা ভাল বিকল্প; mapএবং filterযখন ট্রান্সফর্ম / lambdaপ্রিকেট ফাংশনটি সিটিতে অন্তর্নির্মিত পাইথন হয় এবং পুনরাবৃত্তিযোগ্য তুচ্ছভাবে ছোট হয় না, তবে যখন আপনার লিস্টকম্প / জেনেক্সপ্রাইপ এড়াতে পারে এমন প্রয়োজন হয় তখন এগুলি সর্বদা ধীর হয় ।
শ্যাডোর্যাঞ্জার

13

আমাকে এটি একটি বিশাল তালিকার সাথে করার দরকার ছিল এবং তালিকাটি নকল করা ব্যয়বহুল বলে মনে হয়েছিল, বিশেষত যেহেতু আমার ক্ষেত্রে অপসারণের সংখ্যা অবশিষ্ট আইটেমের তুলনায় কম হবে। আমি এই নিম্ন-স্তরের পদ্ধতির গ্রহণ করেছি।

array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

আমি যা জানি না তা হ'ল বড় তালিকাটি অনুলিপি করার সাথে কয়েক মুছে ফেলা কতটা দক্ষ। আপনার কোনও অন্তর্দৃষ্টি থাকলে কমেন্ট করুন।


আমার ক্ষেত্রে আমাকে সেই 'অবাঞ্ছিত' উপাদানগুলিকে অন্য তালিকায় স্থান দেওয়া দরকার। এই সমাধান সম্পর্কে আপনার কোনও নতুন মন্তব্য আছে? আমি আরও মনে করি যে তালিকাটি নকল করার পরিবর্তে কিছু মুছে ফেলা ব্যবহার করা ভাল।
গুস্তাভোভেলস্কো

পারফরম্যান্স যদি কোনও সমস্যা হয় তবে এটি সঠিক উত্তর (যদিও @ অ্যালেক্সির মতো)। এটি বলেছিল যে, listপ্রথম স্থানে একটি ডাটা স্ট্রাকচার হিসাবে বেছে নেওয়া উচিত সাবধানতার সাথে বিবেচনা করা উচিত যেহেতু একটি তালিকাটির মাঝামাঝি থেকে সরানো তালিকার দৈর্ঘ্যের ক্ষেত্রে রৈখিক সময় নেয়। আপনার যদি সত্যিই কে-থ্রি অনুক্রমিক আইটেমটিতে এলোমেলো অ্যাক্সেসের প্রয়োজন না হয়, তবে বিবেচনা করুন OrderedDict?
সর্বোচ্চ

@ জিভেলাস্কো কেন তৈরি করবেন না newlist = [], তার newlist.append(array[i])ঠিক আগে del array[i]?
সর্বাধিক

2
নোট করুন যে এটি সম্ভবত সময় অকার্যকর: যদি list()কোনও লিঙ্কযুক্ত তালিকা হয়, তবে এলোমেলো অ্যাক্সেস ব্যয়বহুল, যদি list()অ্যারে হয়, মুছে ফেলাগুলি ব্যয়বহুল কারণ তাদের নিম্নলিখিত সমস্ত উপাদানকে এগিয়ে নিয়ে যেতে হবে। একটি শালীন পুনরাবৃত্তকারী লিঙ্কযুক্ত তালিকার প্রয়োগের জন্য জিনিসগুলিকে ভাল করতে পারে। এটি তবে স্থান দক্ষ হতে পারে।
সিরো সান্তিলি 冠状 病毒 审查 六四 事件 法轮功

10

বর্তমান তালিকা আইটেমটি পছন্দসই মানদণ্ডটি পূরণ করে কেবল একটি নতুন তালিকা তৈরি করাও স্মার্ট হতে পারে।

তাই:

for item in originalList:
   if (item != badValue):
        newList.append(item)

এবং নতুন তালিকার নামের সাথে পুরো প্রকল্পটি পুনরায় কোড করা এড়াতে:

originalList[:] = newList

নোট, পাইথন ডকুমেন্টেশন থেকে:

copy.copy (x) এক্স এর অগভীর অনুলিপি ফিরিয়ে দিন।

কপি.দীপকপি (এক্স) এক্স এর গভীর কপি ফিরিয়ে দিন Return


3
এটি কোনও নতুন তথ্য যুক্ত করে না যা বছর পূর্বে গৃহীত উত্তরে ছিল না।
মার্ক অ্যামেরি

2
@ মার্কআমেরি কোনও সমস্যা দেখার সহজ এবং সহজ উপায়। সংক্ষিপ্ত কোডিং সিনট্যাক্স পছন্দ করে না এমন লোকদের জন্য এটি কম ঘনীভূত।
ntk4

9

এই উত্তরটি মূলত এমন প্রশ্নের জবাবে লেখা হয়েছিল যা পরে নকল হিসাবে চিহ্নিত করা হয়েছে: পাইথনের তালিকা থেকে স্থানাঙ্কগুলি সরানো হচ্ছে

আপনার কোডে দুটি সমস্যা রয়েছে:

1) অপসারণ () ব্যবহার করার সময় আপনি পূর্ণসংখ্যা সরানোর চেষ্টা করেন যেখানে আপনাকে একটি টিউপল অপসারণ করতে হবে।

২) ফর লুপটি আপনার তালিকার আইটেমগুলি এড়িয়ে যাবে।

আমরা যখন আপনার কোডটি কার্যকর করি তখন কী ঘটে তা চালানো যাক:

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

প্রথম সমস্যাটি হ'ল আপনি () অপসারণ করতে 'ক' এবং 'বি' উভয় পাশ করছেন, তবে সরান () কেবলমাত্র একটি যুক্তি গ্রহণ করে। তাহলে কীভাবে আমরা আপনার তালিকার সাথে সঠিকভাবে কাজ করতে মুছে ফেলতে পারি ()? আপনার তালিকার প্রতিটি উপাদান কী তা আমাদের খুঁজে বের করতে হবে। এক্ষেত্রে প্রত্যেকেই একটি টিপল। এটি দেখতে, আসুন তালিকার একটি উপাদান অ্যাক্সেস করুন (সূচী 0 থেকে শুরু হয়):

>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

আহা! এল 1 এর প্রতিটি উপাদান আসলে একটি টিপল। সুতরাং এটি অপসারণ করতে আমাদের পাস করা দরকার। পাইথনের টিপলগুলি খুব সহজ, এগুলি কেবল বন্ধনীগুলিতে মানগুলি বদ্ধ করে তৈরি করা হয়। "ক, খ" টিউপল নয়, তবে "(ক, খ)" একটি টিপল। সুতরাং আমরা আপনার কোডটি পরিবর্তন করে আবার চালাব:

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

এই কোডটি কোনও ত্রুটি ছাড়াই চলে, তবে আসুন এটি আউটপুট তালিকাটি দেখুন:

L1 is now: [(1, 2), (5, 6), (1, -2)]

(1, -2) এখনও কেন আপনার তালিকায় রয়েছে? এটি পুনরুক্ত করার জন্য একটি লুপ ব্যবহার করার সময় তালিকার সংশোধন করে দেখা যায় বিশেষ যত্ন না করে খুব খারাপ ধারণা। (1, -2) তালিকায় থাকার কারণটি হ'ল তালিকার মধ্যে থাকা প্রতিটি আইটেমের অবস্থানগুলি লুপটির পুনরাবৃত্তির মধ্যে পরিবর্তিত হয়েছিল। উপরের কোডটি দীর্ঘতর তালিকাতে ফিড দিলে কী ঘটে তা দেখা যাক:

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

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

সবচেয়ে স্বজ্ঞাত সমাধান হ'ল তালিকাটি অনুলিপি করুন, তারপরে মূল তালিকাটি পুনরাবৃত্তি করুন এবং কেবল অনুলিপিটি সংশোধন করুন। আপনি এটির মতো করে চেষ্টা করে দেখতে পারেন:

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

তবে আউটপুটটি আগের মতো হবে:

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

এটি কারণ যখন আমরা এল 2 তৈরি করি তখন পাইথন আসলে কোনও নতুন বস্তু তৈরি করে না। পরিবর্তে, এটি L2 হিসাবে একই বস্তুর কাছে কেবল L2 উল্লেখ করেছে। আমরা এটি 'এর' দিয়ে যাচাই করতে পারি যা নিছক "সমান" (==) থেকে পৃথক।

>>> L2=L1
>>> L1 is L2
True

আমরা copy.copy () ব্যবহার করে একটি সত্য অনুলিপি তৈরি করতে পারি। তারপরে সবকিছু প্রত্যাশার মতো কাজ করে:

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

শেষ পর্যন্ত, এল 1 এর সম্পূর্ণ নতুন কপি তৈরি করার চেয়ে আরও একটি ক্লিনার সমাধান রয়েছে। বিপরীত () ফাংশন:

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

দুর্ভাগ্যক্রমে, আমি বিপরীত () কীভাবে কাজ করে তা পর্যাপ্তরূপে বর্ণনা করতে পারি না। কোনও তালিকা এতে পাস করার পরে এটি একটি 'তালিকার বিপরীতমুখী' অবজেক্ট প্রদান করে। ব্যবহারিক উদ্দেশ্যে, আপনি এটিকে তার যুক্তির বিপরীত অনুলিপি তৈরি হিসাবে ভাবতে পারেন। এটিই আমার সমাধানের সমাধান।


4

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

inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerateআপনাকে একবারে আইটেম এবং সূচীতে অ্যাক্সেস দেয়। reversedআপনি পরে মুছে ফেলা যা সূচকগুলি আপনার উপর পরিবর্তন না হয় যাতে হয়।


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

4

আপনি filter()বিল্ট-ইন হিসাবে উপলব্ধ ব্যবহার করতে চাইতে পারেন ।

আরও তথ্যের জন্য এখানে চেক করুন


4

এখানে বেশিরভাগ উত্তর আপনি তালিকার একটি অনুলিপি তৈরি করতে চান। আমার একটি ব্যবহারের কেস ছিল যেখানে তালিকাটি বেশ দীর্ঘ ছিল (১১০ কে আইটেম) এবং তার পরিবর্তে তালিকাটি হ্রাস করা চতুর ছিল।

সবার আগে আপনাকে ফোরচ লুপটি উইল লুপের সাথে প্রতিস্থাপন করতে হবে ,

i = 0
while i < len(somelist):
    if determine(somelist[i]):
         del somelist[i]
    else:
        i += 1

iযদি ইফ ব্লকের মান পরিবর্তন হয় না কারণ আপনি পুরানো আইটেমটি মুছে ফেলার পরে আপনি একই আইডেক্স থেকে নতুন আইটেমটির মান পেতে চাইবেন।


3

আপনি বিপরীতে লুপিং চেষ্টা করতে পারেন তাই কিছু_ তালিকার জন্য আপনি এর মতো কিছু করবেন:

list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

এইভাবে সূচকটি সারিবদ্ধ হয় এবং তালিকা আপডেটগুলি থেকে ভোগেনা (আপনি প্লে কার্ট উপাদানটি পপ করুন বা না কেন)।


লুপিং আপনার reversed(list(enumerate(some_list)))নিজের তুলনায় ইন্ডেক্সের তুলনায় সহজ হবে।
মার্ক অ্যামেরি

@ মার্ক অ্যামেরি মনে করেন না আপনি এইভাবে তালিকাটি পরিবর্তন করতে পারবেন।
কুইকেগ

3

একটি সম্ভাব্য সমাধান, দরকারী যদি আপনি কেবল কিছু জিনিস অপসারণ করতে চান না, তবে একক লুপে সমস্ত উপাদানগুলির সাথেও কিছু করুন:

alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1

আপনার সত্যিই কেবল বোঝা ব্যবহার করা উচিত। তারা বুঝতে অনেক সহজ।
গরুর মাংস 23

আমি যদি badজিনিসগুলি সরিয়ে নিতে চাই , এটির সাথে goodকিছু করব এবং এক লুপের জিনিসগুলি দিয়েও কিছু করব ?
আলেক্সি

1
প্রকৃতপক্ষে, আমি বুঝতে পারি যে এখানে কিছু চতুরতা রয়েছে যে আপনি একটি খোলা স্লাইস দিয়ে তালিকার একটি অনুলিপি তৈরি করুন ( alist[:]) এবং যেহেতু আপনি কিছু অভিনব কাজটি করতে পারেন, এটিতে আসলে ব্যবহারের ক্ষেত্রে রয়েছে। ভাল রিভিশন ভাল। আমার upvote নিন।
গরুর মাংস

2

আমার অনুরূপ কিছু করার দরকার ছিল এবং আমার ক্ষেত্রে সমস্যা ছিল মেমোরি - আমার একটি তালিকাতে একাধিক ডেটাসেট অবজেক্টগুলি একটি নতুন বস্তু হিসাবে তাদের সাথে কিছু স্টাফ করার পরে প্রয়োজন হয়েছিল এবং প্রতিটি এন্ট্রি থেকে মুক্তি পাওয়ার দরকার ছিল যার সাথে আমি মার্জ হয়ে যাচ্ছিলাম of এগুলির সকলের নকল করা এবং স্মৃতিশক্তি উড়িয়ে দেওয়া এড়িয়ে চলুন। আমার ক্ষেত্রে তালিকার পরিবর্তে একটি অভিধানে অবজেক্টগুলি ভালভাবে কাজ করেছে:

``

k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

``


2

TLDR:

আমি একটি লাইব্রেরি লিখেছি যা আপনাকে এটি করতে দেয়:

from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without "breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

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

কেবল তালিকাগুলি নয়, সমস্ত পরিবর্তনীয় ক্রমগুলিতে কাজ করা উচিত।


পুরো উত্তর:

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

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

এখানfluidIter.py থেকে ডাউনলোড করুন https://github.com/alanbacon/FluidIterator , এটি কেবল একটি একক ফাইল তাই গিট ইনস্টল করার দরকার নেই। কোনও ইনস্টলার নেই তাই ফাইলটি আপনার নিজেরাই অজগর পথে রয়েছে তা নিশ্চিত করতে হবে। কোডটি অজগর 3 এর জন্য লেখা হয়েছে এবং অজগর 2 তে অন্বেষণ করা হয়েছে।

from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                       
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL)) 
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

এটি নিম্নলিখিত আউটপুট উত্পাদন করবে:

initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

উপরে আমরা popতরল তালিকার অবজেক্টে পদ্ধতিটি ব্যবহার করেছি । অন্যান্য সাধারণ iterable পদ্ধতি যেমন হিসাবে প্রয়োগ করা হয় del fluidL[i], .remove, .insert, .append, .extend। তালিকাগুলি ( sortএবং।) ব্যবহার করেও তালিকাটি সংশোধন করা যেতে পারেreverse পদ্ধতিগুলি প্রয়োগ করা হয় না) ।

একমাত্র শর্ত হ'ল আপনাকে অবশ্যই সেই স্থানে তালিকাটি সংশোধন করতে হবে, যদি কোনও বিন্দুতে fluidLবা lকোনও অন্য তালিকাতে পুনরায় নিয়োগ দেওয়া হয় তবে কোডটি কাজ করবে না। মূল fluidLঅবজেক্টটি এখনও লুপের জন্য ব্যবহার করা হত তবে আমাদের সংশোধন করার সুযোগ থেকে যায়।

অর্থাত

fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

যদি আমরা তালিকার বর্তমান সূচক মানটি অ্যাক্সেস করতে চাই তবে আমরা গণনাটি ব্যবহার করতে পারি না, কারণ এটি কেবল গণনা করে যে লুপের জন্য কতবার চালিত হয়েছে। পরিবর্তে আমরা পুনরাবৃত্তকারী অবজেক্টটি সরাসরি ব্যবহার করব।

fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

এটি নিম্নলিখিত আউটপুট হবে:

enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

FluidIterableশ্রেণী শুধু মূল তালিকা বস্তুর জন্য একটি মোড়কের প্রদান করে। মূল অবজেক্টটি তরল পদার্থের সম্পত্তি হিসাবে এরূপে অ্যাক্সেস করা যায়:

originalList = fluidArr.fixedIterable

আরও উদাহরণ / পরীক্ষা if __name__ is "__main__":নীচের অংশে পাওয়া যাবে fluidIter.py। এগুলি দেখার মতো কারণ তারা বিভিন্ন পরিস্থিতিতে কী ঘটে তা ব্যাখ্যা করে। যেমন: একটি স্লাইস ব্যবহার করে তালিকার বৃহত অংশগুলি প্রতিস্থাপন করা। বা লুপগুলির জন্য নেস্টেডে একই পুনরাবৃত্ত হওয়া (এবং সংশোধনকারী) ব্যবহার করা।

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


সম্পাদনা: মন্তব্যে উল্লিখিত হিসাবে, এই উত্তরটি আসলেই এমন কোনও সমস্যা উপস্থাপন করে না যার জন্য এই পদ্ধতির একটি সমাধান সরবরাহ করে। আমি এখানে সম্বোধন করার চেষ্টা করব:

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

অর্থাত

newList = [i for i in oldList if testFunc(i)]

তবে এর ফলাফল যদি ইতিমধ্যে testFuncযুক্ত হওয়া উপাদানগুলির উপর নির্ভর করে newList? বা উপাদান এখনও আছেoldList যে যোগ করা যেতে পারে? একটি তালিকা বোধগম্যতা এখনও ব্যবহার করার একটি উপায় থাকতে পারে তবে এটি এটি কমনীয়তা হারাতে শুরু করবে এবং আমার জন্য এটি একটি জায়গায় তালিকাকে সংশোধন করা সহজ মনে করে।

নীচের কোডটি একটি অ্যালগরিদমের একটি উদাহরণ যা উপরের সমস্যাটি ভুগছে। অ্যালগোরিদম একটি তালিকা হ্রাস করবে যাতে কোনও উপাদান অন্য কোনও উপাদানের একাধিক না হয়।

randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple 
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

আউটপুট এবং চূড়ান্ত হ্রাস তালিকা নীচে প্রদর্শিত হবে

outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]

এটি অতিরিক্ত ইঞ্জিনিয়ারড কিনা তা বলা শক্ত কারণ এটি কোন সমস্যাটি সমাধান করার চেষ্টা করছে তা স্পষ্ট নয়; এই পদ্ধতির ব্যবহার করে উপাদানগুলি অপসারণ কী অর্জন করে যা অর্জন some_list[:] = [x for x in some_list if not some_condition(x)]করে না? এর কোনও উত্তর না দিয়ে কেন কেউ বিশ্বাস করবে যে আপনার 600০০-লাইনের লাইব্রেরিটি টাইপস এবং মন্তব্য-আউট কোড দিয়ে সম্পূর্ণ ডাউনলোড করা এবং ব্যবহার করা ওয়ান লাইনারের চেয়ে তাদের সমস্যার উন্নত সমাধান? -1।
মার্ক অ্যামেরি

@MarkAmery। যখন কেবল কোনও আইটেমের উপর ভিত্তি করে কোনও আইটেম অপসারণ করা উচিত (বা যুক্ত করা বা সরিয়ে নেওয়া) উচিত তা নির্ধারণের চেষ্টা করার সময় প্রধান ব্যবহারের ক্ষেত্রে, তবে তালিকার অন্য আইটেমের অবস্থানে বা তালিকার রাজ্যের হিসাবে পুরো। উদাহরণস্বরূপ, তালিকা বোধগম্যতার সাথে এমন কিছু লেখা সম্ভব নয় some_list[:] = [x for x in some_list if not some_condition(y)]যেখানে কোথা yথেকে আলাদা তালিকা উপাদান রয়েছে x। কিংবা লেখাও সম্ভব হত না some_list[:] = [x for x in some_list if not some_condition(intermediateStateOf_some_list)]
অনুরণন

2

সর্বাধিক কার্যকর পদ্ধতি হ'ল তালিকার বোধগম্যতা, অনেক লোক তাদের কেস দেখায়, অবশ্যই এটি iteratorমাধ্যমে পাওয়ার জন্য এটিও একটি ভাল উপায় filter

Filterএকটি ফাংশন এবং একটি ক্রম প্রাপ্ত। Filterঘুরে প্রতিটি উপাদান প্রেরণ ফাংশন প্রযোজ্য, এবং তারপর ধরে রাখা অথবা ফাংশন ফেরত মান উপর নির্ভর করে উপাদান বাতিল করতে কিনা সিদ্ধান্ত নেয় Trueবা False

এর একটি উদাহরণ রয়েছে (টিপলে প্রতিকূলতা পান):

list(filter(lambda x:x%2==1, (1, 2, 4, 5, 6, 9, 10, 15)))  
# result: [1, 5, 9, 15]

সাবধানতা: আপনি পুনরাবৃত্তিকেও পরিচালনা করতে পারবেন না। Iteilers কখনও কখনও সিক্যুয়েন্স চেয়ে ভাল।


2

লুপ জন্য সূচক মাধ্যমে পুনরাবৃত্তি হবে ..

আপনার একটি তালিকা আছে বিবেচনা করুন,

[5, 7, 13, 29, 65, 91]

আপনি তালিকা পরিবর্তনশীল ব্যবহার করা হয় lis। এবং আপনি সরানোর জন্য একই ব্যবহার করছেন ..

আপনার পরিবর্তনশীল

lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6

5 তম পুনরাবৃত্তির সময়,

আপনার 35 নম্বরটি প্রাথমিক ছিল না তাই আপনি এটিকে তালিকা থেকে সরিয়ে দিয়েছেন।

lis.remove(y)

এবং তারপরে পরবর্তী মান (65) পূর্ববর্তী সূচকগুলিতে যান।

lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5

সুতরাং চতুর্থ পুনরাবৃত্তি সম্পন্ন পয়েন্টার 5 তম দিকে সরানো ..

আপনার লুপটি কেন আগে index৫ টি আচ্ছাদন করে তা আগের সূচীতে স্থানান্তরিত করে।

সুতরাং আপনার অন্য ভেরিয়েবলের মধ্যে রেফারেন্স তালিকাটি দেওয়া উচিত নয় যা অনুলিপিটির পরিবর্তে মূল উল্লেখ করে।

ite = lis #dont do it will reference instead copy

সুতরাং ব্যবহার করে তালিকার অনুলিপি করুন list[::]

এখন আপনি এটি দিতে হবে,

[5, 7, 13, 29]

সমস্যাটি হল আপনি পুনরাবৃত্তির সময় কোনও তালিকা থেকে কোনও মান সরিয়ে ফেললেন তবে আপনার তালিকা সূচকটি ধসে যাবে।

সুতরাং আপনি পরিবর্তে বোঝার চেষ্টা করতে পারেন।

যা সমস্ত পুনরাবৃত্তিযোগ্য যেমন তালিকা, টিপল, ডিক, স্ট্রিং ইত্যাদি সমর্থন করে


এটি আমাকে বুঝতে কেন আমার কোড ব্যর্থ হচ্ছে helped
ওয়াহিদ সাদিক

2

যদি আপনি পুনরাবৃত্তি করার সময় কোনও তালিকা থেকে উপাদানগুলি মুছতে চান তবে কিছুক্ষণের জন্য লুপটি ব্যবহার করুন যাতে আপনি প্রতিটি মুছে ফেলার পরে বর্তমান সূচী এবং শেষ সূচকটি পরিবর্তন করতে পারেন।

উদাহরণ:

i = 0
length = len(list1)

while i < length:
    if condition:
        list1.remove(list1[i])
        i -= 1
        length -= 1

    i += 1

1

অন্যান্য উত্তরগুলি সঠিক যে আপনি পুনরাবৃত্তি করছেন এমন একটি তালিকা থেকে মুছে ফেলা প্রায়শই খারাপ ধারণা। বিপরীত পুনরাবৃত্তি সমস্যাগুলি এড়ায়, তবে কোডটি অনুসরণ করা আরও বেশি কঠিন যে এটি করে, তাই সাধারণত আপনি কোনও তালিকা বোধগম্যতা বা ব্যবহারের চেয়ে ভাল হন filter

তবে, এমন একটি ক্ষেত্রে রয়েছে যেখানে আপনি পুনরাবৃত্তি করছেন এমন ক্রম থেকে উপাদানগুলি সরিয়ে ফেলা নিরাপদ: আপনি পুনরাবৃত্তি করার সময় যদি আপনি কেবল একটি আইটেম সরিয়ে থাকেন। এটি একটি returnবা একটি ব্যবহার করে নিশ্চিত করা যেতে পারে break। উদাহরণ স্বরূপ:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

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


1

আমি আপনার সমস্যা সমাধানের জন্য তিনটি পদ্ধতির কথা ভাবতে পারি। উদাহরণ হিসাবে, আমি টিপলগুলির একটি এলোমেলো তালিকা তৈরি করব somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]। শর্তটি আমি বেছে নিই sum of elements of a tuple = 15। চূড়ান্ত তালিকায় আমাদের কাছে কেবল সেই দ্বিগুণ থাকবে যাদের সমষ্টি 15 এর সমান নয়।

আমি যা বেছে নিয়েছি তা এলোমেলোভাবে নির্বাচিত উদাহরণ। পরিবর্তন করুন মুক্ত মনে tuples একটি তালিকা এবং শর্ত যে, আমি চয়ন করেছেন।

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

for tup in somelist:
    if ( sum(tup)==15 ): 
        del somelist[somelist.index(tup)]

print somelist
>>> [(1, 2, 3), (3, 6, 6), (7, 8, 9), (10, 11, 12)]

পদ্ধতি 2.> একটি নতুন তালিকা তৈরি করুন যাতে উপাদানগুলি (টিপলস) রয়েছে যেখানে প্রদত্ত শর্তটি পূরণ করা হয়নি (প্রদত্ত শর্তটি পূরণ হয় এমন তালিকার উপাদানগুলি সরিয়ে ফেলার মতো এটি একই জিনিস)। নিম্নলিখিতটির জন্য কোডটি নিম্নরূপ:

newlist1 = [somelist[tup] for tup in range(len(somelist)) if(sum(somelist[tup])!=15)]

print newlist1
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

পদ্ধতি 3.> প্রদত্ত শর্তটি পূরণ করা হয় এমন সূচিগুলি সন্ধান করুন এবং তারপরে সেই সূচকের সাথে সম্পর্কিত উপাদানগুলি (টিপলস) সরান। নিম্নলিখিত জন্য নিম্নলিখিত কোড।

indices = [i for i in range(len(somelist)) if(sum(somelist[i])==15)]
newlist2 = [tup for j, tup in enumerate(somelist) if j not in indices]

print newlist2
>>>[(1, 2, 3), (7, 8, 9), (10, 11, 12)]

পদ্ধতি 1 এবং পদ্ধতি 2 পদ্ধতি 3 এর চেয়ে দ্রুত । মেথড 2 এবং মেথড 3 পদ্ধতি 1 এর চেয়ে বেশি দক্ষ। আমি পদ্ধতি 2 পছন্দ । পূর্বোক্ত উদাহরণের জন্য,time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7


0

সত্যিই বড় হওয়ার সম্ভাবনা রয়েছে এমন যে কোনও কিছুর জন্য আমি নিম্নলিখিতটি ব্যবহার করি।

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

এটি অন্য যে কোনও কিছুর চেয়ে দ্রুত গতিযুক্ত হওয়া উচিত।


আমি যেটি পরিমাপ করেছি সেখান থেকে নম্পপি 20 টিরও বেশি উপাদানের তালিকার জন্য দ্রুত হতে শুরু করে এবং 1000 টি উপাদান এবং আরও বেশিগুলির বৃহত তালিকার জন্য> 12x দ্রুত ফিল্টারিংয়ে পৌঁছেছে।
জর্জি

0

কিছু পরিস্থিতিতে, যেখানে আপনি কেবলমাত্র একবারে একটি তালিকা ফিল্টার করার চেয়ে আরও বেশি কিছু করছেন, আপনি পুনরাবৃত্তি করার সময় আপনার পুনরাবৃত্তি পরিবর্তন করতে চান।

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

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p

0

আপনি যদি নতুন তালিকাটি পরে ব্যবহার করেন তবে আপনি এলেমকে কেবল কোনওটিতে সেট করতে পারবেন না এবং তারপরে পরবর্তী লুপটিতে এটি বিচার করুন

for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

এইভাবে, আপনাকে তালিকাটি অনুলিপি করার দরকার নেই এবং এটি বোঝা আরও সহজ।


-1

সংখ্যার একটি তালিকা তৈরি করুন এবং 3 দ্বারা বিভাজ্য এমন কোনও কিছু আপনি মুছে ফেলতে চান,

list_number =[i for i in range(100)]

ব্যবহার করে list comprehension, এটি একটি নতুন তালিকা তৈরি করবে এবং নতুন মেমরির স্থান তৈরি করবে

new_list =[i for i in list_number if i%3!=0]

lambda filterফাংশন ব্যবহার করে, এটি ফলস্বরূপ নতুন তালিকা তৈরি করবে এবং মেমোরি স্পেস গ্রাস করবে

new_list = list(filter(lambda x:x%3!=0, list_number))

নতুন তালিকার জন্য মেমরির জায়গা ব্যয় না করে এবং বিদ্যমান তালিকাকে সংশোধন করুন

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