প্রতিটি লুপের জন্য কোনও ডিজাইনের ত্রুটির জন্য একটি সংগ্রহকে সংশোধন করার জন্য একটি নতুন তালিকা তৈরি করা হচ্ছে?


14

আমি সম্প্রতি Collection was modifiedসি # তে এই সাধারণ অবৈধ অপারেশনটিতে অংশ নিয়েছি এবং আমি এটি পুরোপুরি বুঝতে পারার পরেও মনে হচ্ছে এটি একটি সাধারণ সমস্যা (গুগল, প্রায় 300k ফলাফল!)। তবে এটি কোনও লিস্টের মধ্য দিয়ে যাওয়ার সময় পরিবর্তন করার জন্য এটি একটি যৌক্তিক এবং সোজাসাপ্টা জিনিস বলে মনে হয়।

List<Book> myBooks = new List<Book>();

public void RemoveAllBooks(){
    foreach(Book book in myBooks){
         RemoveBook(book);
    }
}

RemoveBook(Book book){
    if(myBooks.Contains(book)){
         myBooks.Remove(book);
         if(OnBookEvent != null)
            OnBookEvent(this, new EventArgs("Removed"));
    }
}

কিছু লোক পুনরাবৃত্তি করতে অন্য তালিকা তৈরি করবে, তবে এটি কেবল সমস্যাটি ডডিং করছে। আসল সমাধানটি কী, বা এখানে আসল নকশার সমস্যাটি কী? আমরা সকলেই এটি করতে চাইছি বলে মনে হচ্ছে , তবে এটি কি কোনও ডিজাইনের ত্রুটির পরিচায়ক?


আপনি একটি পুনরায় ব্যবহারকারীর ব্যবহার করতে পারেন বা তালিকার শেষ থেকে সরাতে পারেন।
এলডুডেরিনো

@ElDuderino msdn.microsoft.com/en-us/library/dscyy5s0.aspxYou consume an iterator from client code by using a For Each…Next (Visual Basic) or foreach (C#) statementলাইনটি মিস করবেন না
SJuan76

জাভাতে Iterator(আপনি বর্ণিত হিসাবে কাজ করে) এবং ListIterator(আপনার ইচ্ছা মত কাজ করে) আছে। এটি উল্লেখ করবে যে বিভিন্ন ধরণের সংগ্রহ এবং প্রয়োগের ক্ষেত্রে পুনরাবৃত্তির কার্যকারিতা সরবরাহ করার জন্য, Iteratorঅত্যন্ত সীমাবদ্ধ (যদি আপনি একটি ভারসাম্য গাছের মধ্যে একটি নোড মুছে ফেলেন তবে কি ঘটে? next()) ListIteratorকম থাকার কারণে আরও শক্তিশালী হওয়ার সাথে? ব্যবহারের ক্ষেত্রে.
এসজেউন 76

অন্যান্য ভাষায় @ এস জুয়ান 7676 এ এখনও আরও বেশি আইট্রেটর প্রকার রয়েছে, যেমন সি ++ এর সামনে ফরোয়ার্ড ইটারেটর রয়েছে (জাভা এর আইট্রেটারের সমতুল্য), দ্বিদ্বিধায়িত পুনরুক্তি (তালিকার পাঠকের মতো), এলোমেলো প্রবেশের পুনরাবৃত্তি, ইনপুট পুনরায় (যেমন জাভা আইট্রেটারের মতো যা alচ্ছিক ক্রিয়াকলাপ সমর্থন করে না) ) এবং আউটপুট পুনরাবৃত্তকারী (যেমন কেবল লেখার জন্য যা এটি শোনার চেয়ে বেশি কার্যকর)।
জুলে

উত্তর:


10

প্রতিটি লুপের জন্য কোনও ডিজাইনের ত্রুটির জন্য একটি সংগ্রহকে সংশোধন করার জন্য একটি নতুন তালিকা তৈরি করা হচ্ছে?

সংক্ষিপ্ত উত্তর: না

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

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

সূত্র: এমএসডিএন

উপায় দ্বারা, আপনি RemoveAllBooksসহজভাবে নিজের সংক্ষিপ্ত করতে পারেreturn new List<Book>()

এবং একটি বই অপসারণ করতে, আমি একটি ফিল্টারড সংগ্রহ ফিরিয়ে দেওয়ার পরামর্শ দিচ্ছি:

return books.Where(x => x.Author != "Bob").ToList();

একটি সম্ভাব্য শেল্ফ-বাস্তবায়ন দেখতে পাবেন:

public class Shelf
{
    List<Book> books=new List<Book> {
        new Book ("Paul"),
        new Book ("Peter")
    };

    public IEnumerable<Book> getAllBooks(){
        foreach(Book b in books){
            yield return b;
        }
    }

    public void RemovePetersBooks(){
        books= books.Where(x=>x.Author!="Peter").ToList();
    }

    public void EmptyShelf(){
        books = new List<Book> ();
    }

    public Shelf ()
    {
    }
}

public static void Main (string[] args)
{
    Shelf s = new Shelf ();
    foreach (Book b in s.getAllBooks()) {
        Console.WriteLine (b.Author);
    }
    s.RemovePetersBooks ();

    foreach (Book b in s.getAllBooks()) {
        Console.WriteLine (b.Author);
    }
    s.EmptyShelf ();
    foreach (Book b in s.getAllBooks()) {
        Console.WriteLine (b.Author);
    }
}

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

1
@ এসবেনসকভ পিডারসান আপনি ঠিক বলেছেন: ডিআই একটি ত্রুটি হিসাবে পরিবর্তন করার কথা ভাবছিলেন ...
থমাস জাঙ্ক

6

এটি পরিবর্তন করতে একটি নতুন তালিকা তৈরি করা সমস্যার একটি ভাল সমাধান যে তালিকার বিদ্যমান পুনরাবৃত্তি পরিবর্তনের পরে নির্ভরযোগ্যতার সাথে চালিয়ে যেতে পারে না যদি না তারা কীভাবে তালিকাটি পরিবর্তন করে তা জেনে থাকে।

আরেকটি সমাধান হ'ল তালিকার ইন্টারফেসের পরিবর্তে পুনরুক্তি ব্যবহার করে পরিবর্তন করা। এটি কেবল তখনই কাজ করে যদি কেবলমাত্র একজন পুনরুক্তিকারী হতে পারে - এটি একযোগে তালিকার উপরে একাধিক থ্রেডের পুনরাবৃত্তির জন্য সমস্যাটি সমাধান করে না, যা (যতক্ষণ না বাসি তথ্য অ্যাক্সেসযোগ্য তা গ্রহণযোগ্য) একটি নতুন তালিকা তৈরি করে।

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

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

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