জেনেরিক তালিকা থেকে পুনরুক্তি করার সময় উপাদানগুলি কীভাবে সরিয়ে ফেলা যায়?


450

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

আপনি কোনওটির .Remove(element)অভ্যন্তরে ব্যবহার করতে পারবেন না foreach (var element in X)(কারণ এটি Collection was modified; enumeration operation may not execute.ব্যতিক্রমের ফলস্বরূপ ) ... আপনি এটিও ব্যবহার করতে পারবেন না for (int i = 0; i < elements.Count(); i++)এবং .RemoveAt(i)কারণ এটি সংগ্রহের তুলনায় আপনার বর্তমান অবস্থানকে ব্যাহত করে i

এটি করার জন্য কি কোনও মার্জিত উপায় আছে?

উত্তর:


733

লুপের সাথে বিপরীতে আপনার তালিকাটি ইট্রেট করুন:

for (int i = safePendingList.Count - 1; i >= 0; i--)
{
    // some code
    // safePendingList.RemoveAt(i);
}

উদাহরণ:

var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] > 5)
        list.RemoveAt(i);
}
list.ForEach(i => Console.WriteLine(i));

পর্যায়ক্রমে, আপনি এর বিরুদ্ধে পরীক্ষার জন্য একটি প্রাকটিক্ট দিয়ে সরান সমস্ত পদ্ধতি ব্যবহার করতে পারেন :

safePendingList.RemoveAll(item => item.Value == someValue);

এখানে প্রদর্শনের জন্য একটি সরলীকৃত উদাহরণ:

var list = new List<int>(Enumerable.Range(1, 10));
Console.WriteLine("Before:");
list.ForEach(i => Console.WriteLine(i));
list.RemoveAll(i => i > 5);
Console.WriteLine("After:");
list.ForEach(i => Console.WriteLine(i));

19
জাভা থেকে আগতদের জন্য, সি # এর তালিকাটি অ্যারেলিস্টের মতো যা সন্নিবেশ / অপসারণটি হ'ল ও (এন) এবং সূচকের মাধ্যমে পুনরুদ্ধারটি হ'ল (1)। এই না একটি ঐতিহ্যগত লিঙ্ক তালিকা। এটি ক্লাসিক লিঙ্কযুক্ত তালিকার মনে রাখার পরে এই তথ্য কাঠামোটি বর্ণনা করতে সি # শব্দটি "তালিকা" ব্যবহার করে বলে মনে হচ্ছে।
জারোদ স্মিথ

79
'তালিকা' নামে কিছুই বলে না 'লিঙ্কডলিস্ট'। জাভা বাদে অন্য ভাষা থেকে আসা লোকেরা বিভ্রান্ত হতে পারে যখন এটি লিঙ্কযুক্ত তালিকান হবে।
গোলেজট্রোল 14

5
আমি এখানে একটি vb.net অনুসন্ধানের মাধ্যমে শেষ করেছি যাতে কেউ যদি সরানএলের জন্য vb.net সমতুল্য বাক্য গঠন চায়:list.RemoveAll(Function(item) item.Value = somevalue)
সিউডোকোডার

1
এটি জাভাতেও সর্বনিম্ন পরিবর্তনের সাথে কাজ করে: .size()পরিবর্তে .Countএবং .remove(i)পরিবর্তে .removeAt(i)। চতুর - ধন্যবাদ!
শরত্কাল লিওনার্ড

2
আমি পারফরম্যান্সের জন্য একটু পরীক্ষা করেছি এবং এটি পরিণত হয়েছে যে RemoveAll()পিছনের forলুপের চেয়ে তিনগুণ সময় নেয় । সুতরাং আমি অবশ্যই লুপটির সাথে দৃ .়ভাবে আটকে আছি, কমপক্ষে যে ক্ষেত্রে এটি গুরুত্বপূর্ণ in
ক্রশা কে। Rool

84

একটি সহজ এবং সরল সমাধান:

আপনার সংগ্রহে পিছনের দিকে দৌড়াতে এবং RemoveAt(i)উপাদানগুলি সরাতে একটি স্ট্যান্ডার্ড লুপ ব্যবহার করুন ।


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

71

বিপরীত পুনরাবৃত্তি যখন আপনি সংগ্রহ থেকে উপাদানগুলি পুনরাবৃত্তি করার সময় অপসারণ করতে চান তখন মনে রাখা উচিত।

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

ICollection<int> test = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});

foreach (int myInt in test.Reverse<int>())
{
    if (myInt % 2 == 0)
    {
        test.Remove(myInt);
    }
}

7
এটি আমার জন্য পুরোপুরি কাজ করেন। সহজ এবং মার্জিত এবং আমার কোডে ন্যূনতম পরিবর্তন প্রয়োজন।
স্টিফেন ম্যাকডুগল

1
এটি কি কেবল ফ্লিপিন প্রতিভা? এবং আমি @ স্টেফেনম্যাকডুগল এর সাথে একমত, আমাকে লুপগুলির জন্য সেই সি ++ 'ওয়াই ব্যবহার করার দরকার নেই এবং কেবল লিনকিউ দিয়ে উদ্দেশ্য হিসাবে চালিয়ে যাওয়া দরকার।
পাইটর কুলা

5
আমি সরল ফোরচ (পরীক্ষায় আমার মাইন্ড। টোললিস্ট ()) এর চেয়ে কোনও সুবিধা দেখতে পাচ্ছি না {যদি (myInt% 2 == 0) {পরীক্ষা। সরান (মাই আইন্ট); }} আপনাকে এখনও বিপরীতটির জন্য একটি অনুলিপি বরাদ্দ করতে হবে এবং এটি হুকে পরিচয় করিয়ে দেবে? মুহূর্ত - কেন সেখানে বিপরীত।
যাহাভ

11
@ জেদেসাহ হ্যাঁ, Reverse<T>()একটি পুনরুক্তি তৈরি করে যা তালিকার পেছনের দিকে চলে যায় তবে এটি তার জন্য তালিকা হিসাবে একই আকারের অতিরিক্ত বাফার বরাদ্দ করে ( রেফারেন্সসোর্স.মাইক্রোসফট / # সিস্টেমম.কোর / সিস্টেম / লিংক / / )। Reverse<T>কেবল বিপরীত ক্রমে মূল তালিকাটি দিয়ে যায় না (ডাব্লু / ও অতিরিক্ত মেমরি বরাদ্দ)। অতএব উভয় ToList()এবং Reverse()একই মেমরি খরচ (উভয় অনুলিপি তৈরি করুন), তবে ToList()ডেটাতে কিছুই করে না। সাথে Reverse<int>(), আমি অবাক হব কেন তালিকা বিপরীত হয়, কী কারণে।
জাহাভ

1
@ জাভা আমি আপনার বক্তব্যটি দেখতে পাচ্ছি এটি হতাশাব্যঞ্জক যে বাস্তবায়ন Reverse<T>()একটি নতুন বাফার তৈরি করে, আমি কেন এটি প্রয়োজনীয় তা আমি যথেষ্ট নিশ্চিত নই। আমার কাছে মনে হয় যে এর অন্তর্নিহিত কাঠামোর উপর নির্ভর করে Enumerableকমপক্ষে কিছু ক্ষেত্রে রৈখিক স্মৃতি বরাদ্দ না করে বিপরীত পুনরাবৃত্তি অর্জন করা উচিত।
জেদেসাহ

68
 foreach (var item in list.ToList()) {
     list.Remove(item);
 }

আপনি যদি আপনার তালিকায় ".ToList ()" যুক্ত করেন (বা একটি লিনকুইয়ের ক্যোয়ারীর ফলাফল), আপনি "আইটেম" সরাসরি "তালিকা" থেকে সরিয়ে ফেলতে পারেন " সংগ্রহ সংশোধিত হয়েছিল; গণনা ক্রিয়াকলাপটি কার্যকর নাও হতে পারে ।" ত্রুটি. সংকলকটি "তালিকা" এর একটি অনুলিপি তৈরি করে, যাতে আপনি নিরাপদে অ্যারেতে অপসারণ করতে পারেন।

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


6
দক্ষতা যদি গুরুত্বপূর্ণ না হয় তবে এটিই সেরা সমাধান।
ইভানপি

2
এটি দ্রুত এবং আরও পঠনযোগ্য: list.RemoveAll (i => সত্য);
সান্তিয়াগো আরিজিটি

1
@ গ্রেগ লিটল, আমি কি আপনাকে সঠিকভাবে বুঝতে পেরেছিলাম - আপনি যখন টোলিস্ট যুক্ত করেন () সংকলক অনুলিপি করা সংগ্রহের মধ্য দিয়ে যায় তবে মূল থেকে সরিয়ে দেয়?
পাইরেজকি

যদি আপনার তালিকায় সদৃশ আইটেম রয়েছে এবং আপনি কেবল তালিকায় পরে থাকা আইটেমটি সরাতে চান তবে এটি কি ভুল আইটেমটি সরিয়ে দেবে না?
টিম এমবি

এটি কি বস্তুর তালিকার জন্যও কাজ করে?
টম এল সাফাদি

23

উপাদান নির্বাচন না বরং উপাদান আপনি সরানোর চেষ্টা তুলনায় না চান। এটি উপাদানগুলি অপসারণের চেয়ে অনেক বেশি সহজ (এবং সাধারণত আরও কার্যকর)।

var newSequence = (from el in list
                   where el.Something || el.AnotherThing < 0
                   select el);

নীচে মাইকেল ডিলনের দেওয়া মন্তব্যের প্রতিক্রিয়া হিসাবে আমি একটি মন্তব্য হিসাবে এটি পোস্ট করতে চেয়েছিলাম, তবে এটি আমার দীর্ঘসূত্রীর চেয়ে অনেক দীর্ঘ এবং সম্ভবত কার্যকর হতে পারে:

ব্যক্তিগতভাবে, আমি কখনই আইটেমগুলিকে এক-এক করে সরিয়ে ফেলতাম না, যদি আপনার অপসারণের প্রয়োজন হয়, তবে কলটি RemoveAllএকটি প্রাকটিক লাগে এবং কেবল একবার অভ্যন্তরীণ অ্যারেটিকে পুনরায় সাজিয়ে তোলে, যেখানে আপনি মুছে ফেলা প্রতিটি উপাদানগুলির জন্য Removeএকটি Array.Copyঅপারেশন করে। RemoveAllঅনেক বেশি দক্ষ।

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

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


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

22

জেনেরিক তালিকায় ToArray () ব্যবহার করা আপনাকে আপনার জেনেরিক তালিকায় একটি সরান (আইটেম) করতে দেয়:

        List<String> strings = new List<string>() { "a", "b", "c", "d" };
        foreach (string s in strings.ToArray())
        {
            if (s == "b")
                strings.Remove(s);
        }

2
এটি ভুল নয় তবে আমার উল্লেখ করতে হবে যে এটি পুরো তালিকাটি অ্যারেতে অনুলিপি করার জন্য ব্যয় করে আপনি যে আইটেমগুলি অপসারণ করতে চান তার ২ য় "স্টোরেজ" তালিকা তৈরি করার প্রয়োজনকে বাইপাস করে। হাত-বাছাই করা উপাদানগুলির একটি দ্বিতীয় তালিকায় সম্ভবত কম আইটেম থাকবে।
আহমাদ

20

.ToList () ব্যবহার করা আপনার তালিকার একটি অনুলিপি তৈরি করবে, যেমন এই প্রশ্নে ব্যাখ্যা করা হয়েছে: ToList () - এটি কি একটি নতুন তালিকা তৈরি করে?

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

foreach (var item in listTracked.ToList()) {    

        if (DetermineIfRequiresRemoval(item)) {
            listTracked.Remove(item)
        }

     }

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

12

কোন আইটেমটি মুছতে হবে তা নির্ধারণ করে এমন ফাংশনের যদি কোনও পার্শ্ব প্রতিক্রিয়া না ঘটে এবং আইটেমটি রূপান্তরিত করে না (এটি একটি খাঁটি ফাংশন), তবে একটি সহজ এবং দক্ষ (রৈখিক সময়) সমাধান:

list.RemoveAll(condition);

পার্শ্ব প্রতিক্রিয়া থাকলে, আমি এই জাতীয় কিছু ব্যবহার করব:

var toRemove = new HashSet<T>();
foreach(var item in items)
{
     ...
     if(condition)
          toRemove.Add(item);
}
items.RemoveAll(toRemove.Contains);

এটি এখনও লিনিয়ার সময়, ধরে নিচ্ছি হ্যাশটি ভাল। তবে হ্যাশসেটের কারণে এটির বর্ধিত মেমরির ব্যবহার রয়েছে।

অবশেষে যদি আপনার তালিকার একটি IList<T>পরিবর্তে কেবল একটি হয় তবে List<T>আমি আমার উত্তরটি প্রস্তাব করব কীভাবে আমি এই বিশেষ অগ্রণী পুনরাবৃত্তি করতে পারি? IList<T>এটিতে অন্যান্য বহু উত্তরের চতুর্ভুজ রানটাইমের সাথে তুলনা করে রৈখিক রানটাইম দেওয়া হবে ।


11

যেহেতু কোনও অপসারণ শর্তে নেওয়া হয় আপনি ব্যবহার করতে পারেন

list.RemoveAll(item => item.Value == someValue);

প্রসেসিংটি আইটেমটি রূপান্তরিত না করে এবং এর কোনও পার্শ্ব প্রতিক্রিয়া না থাকলে এটিই সেরা সমাধান।
কোডসইনচাউস


8

আপনি ফোরচ ব্যবহার করতে পারবেন না তবে আপনি কোনও আইটেম সরিয়ে ফেললে আপনি ফরোয়ার্ডগুলি পুনরাবৃত্তি করতে এবং আপনার লুপ সূচক পরিবর্তনশীল পরিচালনা করতে পারবেন:

for (int i = 0; i < elements.Count; i++)
{
    if (<condition>)
    {
        // Decrement the loop counter to iterate this index again, since later elements will get moved down during the remove operation.
        elements.RemoveAt(i--);
    }
}

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


6

সেই তালিকাটি পুনরাবৃত্তি করার সময় কোনও তালিকার ব্যবহার Removeবা RemoveAtব্যবহারের উদ্দেশ্যটি ইচ্ছাকৃতভাবে কঠিন হয়ে উঠেছে, কারণ এটি প্রায়শই করা ভুল কাজ । আপনি এটি কিছু চালাক কৌশলে কাজ করতে সক্ষম হতে পারেন তবে এটি অত্যন্ত ধীর হবে। প্রতিবার আপনি যখন কল করবেন Removeতখন আপনাকে যে উপাদানটি সরাতে চান সেগুলি খুঁজতে সম্পূর্ণ তালিকাটি স্ক্যান করতে হবে। যতবার আপনি RemoveAtএটি কল করবেন ততক্ষণে পরবর্তী উপাদানগুলি 1 টি বাম দিকে নিয়ে যেতে হবে। যেমন, কোনো সলিউশন ব্যবহার Removeবা RemoveAt, হবে দ্বিঘাত সময় প্রয়োজন, হে (ছিল n ²)

পারলে ব্যবহার করুন RemoveAll। তা না হলে, নিম্নলিখিত প্যাটার্ন তালিকা ফিল্টার করবে ইন-জায়গা রৈখিক সময়, এ হে (ঢ)

// Create a list to be filtered
IList<int> elements = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// Filter the list
int kept = 0;
for (int i = 0; i < elements.Count; i++) {
    // Test whether this is an element that we want to keep.
    if (elements[i] % 3 > 0) {
        // Add it to the list of kept elements.
        elements[kept] = elements[i];
        kept++;
    }
}
// Unfortunately IList has no Resize method. So instead we
// remove the last element of the list until: elements.Count == kept.
while (kept < elements.Count) elements.RemoveAt(elements.Count-1);

3

আমি চাই "প্যাটার্ন "টি এরকম কিছু ছিল:

foreach( thing in thingpile )
{
    if( /* condition#1 */ )
    {
        foreach.markfordeleting( thing );
    }
    elseif( /* condition#2 */ )
    {
        foreach.markforkeeping( thing );
    }
} 
foreachcompleted
{
    // then the programmer's choices would be:

    // delete everything that was marked for deleting
    foreach.deletenow(thingpile); 

    // ...or... keep only things that were marked for keeping
    foreach.keepnow(thingpile);

    // ...or even... make a new list of the unmarked items
    others = foreach.unmarked(thingpile);   
}

এটি প্রোগ্রামারের মস্তিষ্কে যে প্রক্রিয়াটি চলছে তার সাথে কোডটি প্রান্তিককরণ করবে।


1
যথেষ্ট সহজ কেবল একটি বুলিয়ান পতাকা অ্যারে তৈরি করুন (একটি 3-রাজ্যের ধরণ ব্যবহার করুন, উদাহরণস্বরূপ Nullable<bool>, আপনি যদি চিহ্ন ছাড়াই অনুমতি দিতে চান), তবে আইটেমগুলি সরিয়ে / রাখার জন্য ভবিষ্যতের পূর্বে এটি ব্যবহার করুন।
ড্যান বেচার্ড

3

অনুমান করে যে শিকারী কোনও উপাদানটির বুলিয়ান সম্পত্তি, যদি এটি সত্য হয় তবে উপাদানটি সরানো উচিত:

        int i = 0;
        while (i < list.Count())
        {
            if (list[i].predicate == true)
            {
                list.RemoveAt(i);
                continue;
            }
            i++;
        }

আমি এটিকে একটি উত্সাহ দিয়েছিলাম কারণ কখনও কখনও তালিকার ক্রম (বিপরীত ক্রম নয়) এর মধ্য দিয়ে চলা আরও দক্ষ হতে পারে। তালিকাটি অর্ডার করা হওয়ায় প্রথম আইটেমটি সরিয়ে না ফেললে সম্ভবত আপনি থামতে পারেন। (একটি 'বিরতি' কল্পনা করুন যেখানে i++ এই উদাহরণে রয়েছে
ফ্র্যাঙ্কক্রামনো

3

আমি একটি লিনকিউ ক্যোয়ারী থেকে তালিকাটি পুনরায় সাইন করব যেগুলি আপনি রাখতে চান না এমন উপাদানগুলি ফিল্টার করে।

list = list.Where(item => ...).ToList();

তালিকাটি যদি খুব বড় না হয় তবে এটি করার ক্ষেত্রে কোনও উল্লেখযোগ্য পারফরম্যান্সের সমস্যা হওয়া উচিত নয়।


3

কোনও তালিকা থেকে আইটেমগুলি সরিয়ে ফেলার সর্বোত্তম উপায় হ'ল এটি ব্যবহার করা RemoveAll() । তবে লোকেরা রচিত প্রধান উদ্বেগ হ'ল লুপের ভিতরে তাদের কয়েকটি জটিল কাজ করতে হবে এবং / অথবা জটিল তুলনামূলক কেসগুলি থাকতে হবে।

সমাধানটি এখনও ব্যবহার করতে হয় RemoveAll()তবে এই স্বরলিপিটি ব্যবহার করে:

var list = new List<int>(Enumerable.Range(1, 10));
list.RemoveAll(item => 
{
    // Do some complex operations here
    // Or even some operations on the items
    SomeFunction(item);
    // In the end return true if the item is to be removed. False otherwise
    return item > 5;
});

2
foreach(var item in list.ToList())

{

if(item.Delete) list.Remove(item);

}

কেবল প্রথমটি থেকে সম্পূর্ণ নতুন তালিকা তৈরি করুন। আমি পুরোপুরি নতুন তালিকা তৈরি করা হিসাবে "রাইট" না দিয়ে "সহজ" বলি সম্ভবত পূর্ববর্তী পদ্ধতির তুলনায় পারফরম্যান্সের প্রিমিয়ামে আসে (আমি কোনও মানদণ্ড নিয়ে মাথা ঘামাইনি)) আমি সাধারণত এই প্যাটার্নটিকেই পছন্দ করি, এটিও কাটিয়ে উঠতে কার্যকর হতে পারে লিনাক-টু-সত্তা সীমাবদ্ধতা।

for(i = list.Count()-1;i>=0;i--)

{

item=list[i];

if (item.Delete) list.Remove(item);

}

এইভাবে সরল পুরানো ফর লুপের সাথে তালিকার পাশের দিকে চক্র। সংগ্রহের আকার পরিবর্তিত হলে এই ফরোয়ার্ডগুলি করা সমস্যাযুক্ত হতে পারে তবে পিছনের দিকে সর্বদা নিরাপদ থাকা উচিত।


1

আপনি পুনরাবৃত্তি করছেন তালিকাটি অনুলিপি করুন। তারপরে অনুলিপিটি থেকে সরান এবং আসলটি ইন্টারেস্ট করুন। পিছনে যাওয়া বিভ্রান্তিকর এবং সমান্তরালে লুপ করার সময় ভাল কাজ করে না।

var ids = new List<int> { 1, 2, 3, 4 };
var iterableIds = ids.ToList();

Parallel.ForEach(iterableIds, id =>
{
    ids.Remove(id);
});

1

আমি এই মত করব

using System.IO;
using System;
using System.Collections.Generic;

class Author
    {
        public string Firstname;
        public string Lastname;
        public int no;
    }

class Program
{
    private static bool isEven(int i) 
    { 
        return ((i % 2) == 0); 
    } 

    static void Main()
    {    
        var authorsList = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", no = 2 },
            new Author{ Firstname = "Fred", Lastname = "Jones", no = 3 },
            new Author{ Firstname = "Brian", Lastname = "Brains", no = 4 },
            new Author{ Firstname = "Billy", Lastname = "TheKid", no = 1 }
        };

        authorsList.RemoveAll(item => isEven(item.no));

        foreach(var auth in authorsList)
        {
            Console.WriteLine(auth.Firstname + " " + auth.Lastname);
        }
    }
}

আউটপুট

Fred Jones
Billy TheKid

0

আমি নিজেকে একটি অনুরূপ পরিস্থিতিতে পেয়েছি যেখানে আমাকে প্রদত্ত প্রতিটি এন উপাদান মুছে ফেলতে হয়েছিল List<T>

for (int i = 0, j = 0, n = 3; i < list.Count; i++)
{
    if ((j + 1) % n == 0) //Check current iteration is at the nth interval
    {
        list.RemoveAt(i);
        j++; //This extra addition is necessary. Without it j will wrap
             //down to zero, which will throw off our index.
    }
    j++; //This will always advance the j counter
}

0

তালিকা থেকে কোনও আইটেম সরানোর ব্যয়টি অপসারণের পরে আইটেমের সংখ্যার সাথে সমানুপাতিক। যদি আইটেমের প্রথম অর্ধেক অপসারণের যোগ্যতা অর্জন করে তবে পৃথকভাবে আইটেমগুলি অপসারণের উপর ভিত্তি করে যে কোনও পদ্ধতির N * N / 4 আইটেম-অনুলিপি অপারেশনগুলি সম্পাদন করতে হবে, যা তালিকাটি বড় হলে খুব ব্যয়বহুল হতে পারে ।

প্রথম আইটেমটি সরিয়ে ফেলা (যদি থাকে তবে) খুঁজে পেতে তালিকার মাধ্যমে দ্রুত স্ক্যান করা এবং তারপরে সেই বিন্দু থেকে প্রতিটি আইটেমটি যেখানে এটি সম্পর্কিত সেখানে ধরে রাখা উচিত copy এটি সম্পন্ন হয়ে গেলে, আর আইটেমগুলি বজায় রাখা উচিত, তালিকার প্রথম আর আইটেমগুলি সেই আর আইটেমগুলি হবে এবং মুছে ফেলার জন্য প্রয়োজনীয় সমস্ত আইটেম শেষে থাকবে। যদি এই আইটেমগুলি বিপরীত ক্রমে মুছে ফেলা হয়, সিস্টেমটি তাদের কোনওটি অনুলিপি করার পরে শেষ হবে না, সুতরাং তালিকায় যদি এন আইটেম থাকে যা প্রথম এফ সহ সমস্ত আইটেম ধরে রাখা হয়, তবে এটি প্রয়োজনীয় হবে আরএফ আইটেমগুলি অনুলিপি করুন এবং একটি আইটেম এনআর বার দ্বারা তালিকা সঙ্কুচিত করুন। সব লিনিয়ার সময়।


0

আমার পদ্ধতিটি হ'ল আমি প্রথমে সূচকগুলির একটি তালিকা তৈরি করি, যা মুছে ফেলা উচিত। এরপরে আমি সূচকগুলি লুপ করে এবং প্রাথমিক তালিকা থেকে আইটেমগুলি সরিয়ে ফেলি। এটি এর মতো দেখাচ্ছে:

var messageList = ...;
// Restrict your list to certain criteria
var customMessageList = messageList.FindAll(m => m.UserId == someId);

if (customMessageList != null && customMessageList.Count > 0)
{
    // Create list with positions in origin list
    List<int> positionList = new List<int>();
    foreach (var message in customMessageList)
    {
        var position = messageList.FindIndex(m => m.MessageId == message.MessageId);
        if (position != -1)
            positionList.Add(position);
    }
    // To be able to remove the items in the origin list, we do it backwards
    // so that the order of indices stays the same
    positionList = positionList.OrderByDescending(p => p).ToList();
    foreach (var position in positionList)
    {
        messageList.RemoveAt(position);
    }
}

0

সি # তে একটি সহজ উপায় হ'ল আপনি মুছে ফেলতে ইচ্ছুক চিহ্নিত করুন এবং তারপরে পুনরাবৃত্তি করার জন্য একটি নতুন তালিকা তৈরি করুন ...

foreach(var item in list.ToList()){if(item.Delete) list.Remove(item);}  

বা এমনকি সহজ ব্যবহার লিনক ....

list.RemoveAll(p=>p.Delete);

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


0

কোনও সম্পত্তি দিয়ে মুছে ফেলার জন্য উপাদানগুলি সন্ধান করুন এবং প্রক্রিয়া শেষে সেগুলি সরিয়ে দিন।

using System.Linq;

List<MyProperty> _Group = new List<MyProperty>();
// ... add elements

bool cond = true;
foreach (MyProperty currObj in _Group)
{
    if (cond) 
    {
        // SET - element can be deleted
        currObj.REMOVE_ME = true;
    }
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);

0

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

ArrayList place_holder = new ArrayList();
place_holder.Add("1");
place_holder.Add("2");
place_holder.Add("3");
place_holder.Add("4");

for(int i = place_holder.Count-1; i>= 0; i--){
    if(i>= place_holder.Count){
        i = place_holder.Count-1; 
    }

// some method that removes multiple elements here
}

-4
myList.RemoveAt(i--);

simples;

1
simples;এখানে কি করে ?
ডেনি

6
তার একটি প্রতিনিধি .. এটা আমার উত্তর প্রত্যেক সময় এটা সঞ্চালিত downvotes
দঃপঃ

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