একটি পূর্বাঞ্চ মাধ্যমে পিছনে পুনরাবৃত্তি সম্ভব?


129

আমি জানি আমি একটি forবিবৃতি ব্যবহার করতে এবং একই প্রভাব অর্জন করতে পারি, তবে আমি কি foreachসি # এর লুপের সাহায্যে পিছনের দিকে লুপ করতে পারি ?


6
আপনি প্রতিটি করার আগে তালিকায় থাকা উপাদান (list.Rversvers ()) বিপরীত করতে পারেন।
আকান্থান


আপনাকে অঙ্কের সমস্ত উপাদান ইনস্ট্যান্ট করতে হবে যাতে আপনি তাদের ক্রমটি বিপরীত করতে পারেন। এটা সম্ভব নাও হতে পারে। ক্রমটি বিবেচনা করুন: IEnumerable<int> Infinity() { int i = 1; while (true) yield return i++; }আপনি কীভাবে এটি বিপরীত করবেন?
সানক্যাট 2000 2000

উত্তর:


84

একটি তালিকার সাথে কাজ করার সময় (সরাসরি সূচীকরণ), আপনি এটি ব্যবহারের মতো দক্ষতার সাথে এটি করতে পারবেন না for লুপ ।

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


3
আমি আপনার শেষ বিবৃতিটি কিছুটা সাধারণ দেখতে পেয়েছি। অবশ্যই কিছু ক্ষেত্রে রয়েছে যেমন, উদাহরণস্বরূপ, কোনও ধরণের আইনিম্যুয়ালকে ক্রম দিয়ে পুনরুক্ত করা দরকার? আপনি কি এই ক্ষেত্রে foreach ব্যবহার করবেন না? আপনি কি ব্যবহার করবেন?
avl_swen 15

1
আপডেট: লিনক ব্যবহার করে আরও দুটি আধুনিক উত্তরের জন্য [একই ধরণের প্রশ্নের ব্রায়ানের উত্তর দেখুন ([ স্ট্যাকওভারফ্লো.com/ a/ 3320924 / 199364 ), এবং উভয় তালিকাগুলি এবং অন্যান্য সংখ্যাগুণ সম্পর্কে আলোচনা করুন।
নির্মাতা স্টিভ

আপডেট: জন স্কিটির একটি আরও মার্জিত উত্তর রয়েছে, এটি এখন সম্ভব, " yield return" ব্যবহার করে ।
টুলমেকারস্টেভ

2
আমি @ ওএল_সুইডেনের মতো একই প্রাথমিক প্রতিক্রিয়া দেখিয়েছিলাম - "ক্রমের উপর নির্ভরশীল পুনরাবৃত্তিটি পূর্বাঞ্চ ব্যবহার করা উচিত নয়" শব্দগুলি ওভার-ব্রড হয়। হ্যাঁ, অর্ডার-স্বতন্ত্র সমান্তরাল কার্য প্রকাশের জন্য অগ্রণীতা ভাল। তবে এটি আধুনিক পুনরাবৃত্ত-ভিত্তিক প্রোগ্রামিংয়ের একটি প্রয়োজনীয় অংশ । সম্ভবত মুল বক্তব্যটি হ'ল এটি পরিষ্কার / নিরাপদ হবে যদি দুটি স্বতন্ত্র কীওয়ার্ড থাকে , তবে একটি স্পষ্ট করে বলতে পারে যে কেউ পুনরুক্তিগুলি আদেশ-স্বতন্ত্র বলে জোর দিচ্ছে কিনা ? [আইফেলের মতো এমন একটি ভাষা দেওয়া হয়েছে যা চুক্তির প্রচার করতে পারে, যেমন উত্থাপন দেওয়া কোডের জন্য যথাযথভাবে সত্য বা মিথ্যা হতে পারে]]
টুলমেকারস্টেভ

2
ফোরচ "উপাদানগুলি সূচক এবং পুনরাবৃত্তির ক্রম থেকে পৃথক লুপগুলি প্রকাশের জন্য তৈরি" ধারণাটি ভুল। সি # ভাষার স্পেসিফিকেশনের জন্য অগ্রণীকরণ প্রক্রিয়া উপাদানগুলির ক্রম প্রয়োজন। হয় পুনরাবৃত্তকারীদের উপর মুভনেক্সট ব্যবহার করে বা শূন্য থেকে শুরু সূচকগুলিতে প্রক্রিয়াজাতকরণ এবং অ্যারেগুলির প্রতিটি পুনরাবৃত্তিতে এক দ্বারা বাড়ানো।
ডোনাল্ড রিচ

145

আপনি .NET 3.5 এ থাকলে আপনি এটি করতে পারেন:

IEnumerable<int> enumerableThing = ...;
foreach (var x in enumerableThing.Reverse())

এটি খুব কার্যকরী নয় কারণ এটিকে মূলত প্রতিটি স্ট্যাকের মধ্যে রেখে এন्युমিটার ফরোয়ার্ডগুলি দিয়ে যেতে হয় তারপরে বিপরীত ক্রমে সমস্ত কিছু পিছনে ফেলে দেওয়া হয়।

আপনার যদি সরাসরি ইনডেক্সযোগ্য সংগ্রহ (যেমন IList) থাকে তবে আপনার অবশ্যই একটি ব্যবহার করা উচিত for পরিবর্তে লুপ ।

যদি আপনি .NET 2.0 এ থাকেন এবং লুপের জন্য কোনও ব্যবহার করতে না পারেন (যেমন আপনার কাছে কেবল একটি অনুমানযোগ্য) তবে আপনাকে কেবল নিজের বিপরীত ফাংশনটি লিখতে হবে। এই কাজ করা উচিত:

static IEnumerable<T> Reverse<T>(IEnumerable<T> input)
{
    return new Stack<T>(input);
}

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

এটি এবং .NET 3.5 Reverse()এক্সটেনশান পদ্ধতিটি আপনি যদি এমন একটি অনুভূতি খাওয়ান যা স্পষ্টভাবে ফুরিয়ে যাবে যা কখনই আইটেমগুলি ফিরিয়ে দেয় না।


এছাড়াও আমি। নেট ভি 2 শুধুমাত্র উল্লেখ করতে ভুলে গেছি
জেএল।

4
আকর্ষণীয় .NET 2.0 সমাধান।
রিচার্ডড

11
আমি কি কিছু মিস করছি বা আপনার। নেট 3.5 সমাধানটি আসলে কাজ করছে না? বিপরীতমুখী () তালিকাটি উল্টো জায়গায় দেয় এবং এটি ফেরত দেয় না। খুব খারাপ, আমি যেমন সমাধানের আশা করছিলাম।
ব্যবহারকারী 12861

2
কিছু প্রশাসক এই উত্তরটি WRONG হিসাবে চিহ্নিত করুন দয়া করে। বিপরীত () একটি অকার্যকর [1] এবং সুতরাং উপরোক্ত উদাহরণ একটি সংকলন ত্রুটির দিকে পরিচালিত করে। [1] msdn.microsoft.com/en-us/library/b0axc2h2(v=vs.110).aspx
MickyD

6
@ ব্যবহারকারী 12861, মিকি ডানকান: উত্তরটি ভুল নয়, আপনি কিছু মিস করছেন। সিস্টেম.কলেকশনস.জেনারিক.লিস্ট <টি> -এ একটি বিপরীত পদ্ধতি রয়েছে যা একটি জায়গাটিতে বিপরীত করে। নেট নেট ৩.৫-এ বিপরীত নামের আইনিউবারেবল <T> তে একটি এক্সটেনশন পদ্ধতি রয়েছে। এটিকে আরও স্পষ্ট করার জন্য আমি উদাহরণটি var থেকে IEnumerable <int> এ পরিবর্তন করেছি।
ম্যাট হাওয়েলস

55

যেমন 280Z28 বলেছেন, একটির জন্য IList<T>আপনি কেবল সূচকটি ব্যবহার করতে পারেন। আপনি এটি কোনও এক্সটেনশন পদ্ধতিতে লুকিয়ে রাখতে পারেন:

public static IEnumerable<T> FastReverse<T>(this IList<T> items)
{
    for (int i = items.Count-1; i >= 0; i--)
    {
        yield return items[i];
    }
}

এটি Enumerable.Reverse()প্রথমে সমস্ত ডেটা বাফার করে তার চেয়ে দ্রুত হবে । (আমি বিশ্বাস করি না যে Reverseএটির মতো কোনও অপ্টিমাইজেশন প্রয়োগ করা হয়েছে Count())) নোট করুন যে এই বাফারিংয়ের অর্থ হ'ল আপনি যখন প্রথম পুনরাবৃত্তি শুরু করবেন তখন ডেটা সম্পূর্ণরূপে পড়া হবেFastReverse হবে আপনি পুনরাবৃত্তি করার সময় তালিকায় যে কোনও পরিবর্তন হয়েছে "দেখুন"। (আপনি পুনরাবৃত্তির মধ্যে একাধিক আইটেম সরিয়ে ফেললে এটিও ভেঙে যাবে))

সাধারণ ক্রমগুলির জন্য, বিপরীতে পুনরাবৃত্তি করার কোনও উপায় নেই - অনুক্রমটি অসীম হতে পারে, উদাহরণস্বরূপ:

public static IEnumerable<T> GetStringsOfIncreasingSize()
{
    string ret = "";
    while (true)
    {
        yield return ret;
        ret = ret + "x";
    }
}

আপনি যদি উল্টোদিকে পুনরাবৃত্তি করার চেষ্টা করেন তবে আপনি কী হওয়ার আশা করবেন?


কেবল কৌতূহল, কেন "> -1" এর পরিবর্তে "> = 0" ব্যবহার করবেন?
ক্রিস এস

15
> কেন "> -1" এর পরিবর্তে "> = 0" ব্যবহার করবেন? কারণ> = 0 কোডটি পড়ার জন্য মানুষের উদ্দেশ্য সম্পর্কে আরও ভালভাবে যোগাযোগ করে। সংকলকটি এর সমতুল্য> -1 এর সাথে অপ্টিমাইজ করতে সক্ষম হওয়া উচিত যদি এটি করা পারফরম্যান্সে উন্নতি করে।
মার্ক মাসলার

1
ফাস্টআরভার্স (এই আইলিস্ট <টি> আইটেমগুলি) ফাস্টআরওভার্স <T> (এই আইলিস্ট <টি> আইটেমগুলি হতে হবে :) :)
রব

বিভক্ত লাঠি 0 <= i আরও ভাল। বেশ কয়েক বছর বাচ্চাকে গণিত শেখানোর পরে এবং কোডিং দিয়ে মানুষকে সহায়তা করার পরে আমি দেখতে পেলাম যে লোকেরা যে ত্রুটিগুলি কমায় তা হ্রাস করে যদি তারা সবসময় একটি> বি টু <বি পরিবর্তন করে তবে কোনও লাইনের প্রাকৃতিক ক্রমে আসে সংখ্যার (বা একটি সমন্বিত সিস্টেমের এক্স অক্ষ) - একমাত্র ব্যর্থতা যদি আপনাকে এক্সএমএলে কোনও সমীকরণ পেস্ট করতে হয় তবে একটি .config বলুন
এস্কে রাহ্ন

13

foreachপুনরাবৃত্তির জন্য ব্যবহার করার আগে , reverseপদ্ধতিটি দ্বারা তালিকাটি বিপরীত করুন :

    myList.Reverse();
    foreach( List listItem in myList)
    {
       Console.WriteLine(listItem);
    }


কী myListহবে সে সম্পর্কে সতর্কতার একটি শব্দ সহায়ক। IEnumerable. বিপরীত এখানে কাজ করবে না।
নওফাল

2
@ এমএ-মাদদিন দুজনই আলাদা। আমি অনুমান করি উত্তরদাতা তালিকার <T> উপর নির্ভর করছেন which
নওফাল

আসলে, কেন জানি আমি জানি না। আমার আরও বিশদ যুক্ত করা উচিত ছিল ... যাইহোক এটি বিভ্রান্তিকর কোড যেহেতু myListমনে হয় ধরণের System.Collections.Generic.List<System.Windows.Documents.List>(বা অন্য কোনও কাস্টম Listটাইপ) অন্যথায় এই কোডটি কাজ করে না: পি
মার্টিন স্নাইডার

5

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

লিনক অর্ডারবাইডিজেন্ডিংয়ের জন্য বাছাইকরণ কী সরবরাহ করতে লিনক সিলেক্ট সহ বেনামে টাইপ ব্যবহার করে একটি লিনক এক্সটেনশন পদ্ধতি;

    public static IEnumerable<T> Invert<T>(this IEnumerable<T> source)
    {
        var transform = source.Select(
            (o, i) => new
            {
                Index = i,
                Object = o
            });

        return transform.OrderByDescending(o => o.Index)
                        .Select(o => o.Object);
    }

ব্যবহার:

    var eable = new[]{ "a", "b", "c" };

    foreach(var o in eable.Invert())
    {
        Console.WriteLine(o);
    }

    // "c", "b", "a"

এটি "বিপরীতমুখী" নামকরণ করা হয়েছে কারণ এটি "বিপরীত" এর সমার্থক এবং তালিকা বিপরীত বাস্তবায়নের সাথে অসঙ্গতি সক্ষম করে।

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

    public static IEnumerable<T> Invert<T>(this IEnumerable<T> source, int index, int count)
    {
        var transform = source.Select(
            (o, i) => new
            {
                Index = i < index ? Int32.MaxValue : i >= index + count ? Int32.MinValue : i,
                Object = o
            });

        return transform.OrderByDescending(o => o.Index)
                        .Select(o => o.Object);
    }

ব্যবহার:

    var eable = new[]{ "a", "b", "c", "d" };

    foreach(var o in eable.Invert(1, 2))
    {
        Console.WriteLine(o);
    }

    // "a", "c", "b", "d"

আমি এই লিঙ্ক বাস্তবায়নের বনাম কোনও অস্থায়ী তালিকা ব্যবহারের বিপরীতে সংগ্রহের জন্য মোড়কে ব্যবহারের পারফরম্যান্সের হিট সম্পর্কে নিশ্চিত নই।


লেখার সময়, আমি লিনকের নিজস্ব বিপরীত বাস্তবায়ন সম্পর্কে অবগত ছিলাম না, এটি কাজ করে মজাদার হয়েছিল। https://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx


4

আপনি যদি একটি তালিকা ব্যবহার করেন <T>, আপনি এই কোডটিও ব্যবহার করতে পারেন:

List<string> list = new List<string>();
list.Add("1");
list.Add("2");
list.Add("3");
list.Reverse();

এটি এমন একটি পদ্ধতি যা তালিকায় নিজেকে উল্টে লিখবে।

এখন ভবিষ্যদ্বাণী:

foreach(string s in list)
{
    Console.WriteLine(s);
}

আউটপুটটি হ'ল:

3
2
1

3

আপনি যদি সংগ্রহের কোডটি পরিবর্তন করতে পারেন তবে এটি সম্ভব IEnumerable বা IEnumerable (যেমন IList এর নিজস্ব প্রয়োগকরণ) প্রয়োগ করেন ।

আপনার জন্য এই কাজটি করে একটি আইট্রেটর তৈরি করুন , উদাহরণস্বরূপ আইইনুমারেবল ইন্টারফেসের মাধ্যমে নিম্নলিখিত প্রয়োগকরণের মতো ('আইটেমগুলি ধরে নেওয়া এই নমুনায় একটি তালিকা ক্ষেত্র):

public IEnumerator<TObject> GetEnumerator()
{
    for (var i = items.Count - 1; i >= 0; i--)
    { 
        yield return items[i];
    }
}

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

এর কারণে আপনার তালিকাটি আপনার তালিকার মাধ্যমে বিপরীত ক্রমে পুনরাবৃত্তি হবে।

কেবল একটি ইঙ্গিত: ডকুমেন্টেশনের মধ্যে আপনার তালিকাটির এই বিশেষ আচরণটি স্পষ্টভাবে বর্ণনা করা উচিত (স্ট্যাক বা কুইয়ের মতো স্ব-ব্যাখ্যাকারী শ্রেণীর নামটি বেছে নেওয়ার মাধ্যমে আরও ভাল)।


2

না। প্রতিটি আইটেমের জন্য সংগ্রহের মাধ্যমে প্রতিটি পুনরাবৃত্তি করে এবং অর্ডার নির্ভর করে এটি আইইনামেবল বা গেটইনুমেরেটর () ব্যবহার করে কিনা।


1
ওয়েল সেখানে হয় আদেশের নিশ্চয়তা, সংগ্রহ ধরনের উপর নির্ভর করে।
জন স্কিটি

1

জন স্কিটির চমৎকার উত্তরের বিষয়ে কিছুটা বিশদভাবে বর্ণনা করা , এটি বহুমুখী হতে পারে:

public static IEnumerable<T> Directional<T>(this IList<T> items, bool Forwards) {
    if (Forwards) foreach (T item in items) yield return item;
    else for (int i = items.Count-1; 0<=i; i--) yield return items[i];
}

এবং তারপর হিসাবে ব্যবহার করুন

foreach (var item in myList.Directional(forwardsCondition)) {
    .
    .
}

-1

আমি এই কোডটি ব্যবহার করেছি যা কাজ করে

                if (element.HasAttributes) {

                    foreach(var attr in element.Attributes().Reverse())
                    {

                        if (depth > 1)
                        {
                            elements_upper_hierarchy_text = "";
                            foreach (var ancest  in element.Ancestors().Reverse())
                            {
                                elements_upper_hierarchy_text += ancest.Name + "_";
                            }// foreach(var ancest  in element.Ancestors())

                        }//if (depth > 1)
                        xml_taglist_report += " " + depth  + " " + elements_upper_hierarchy_text+ element.Name + "_" + attr.Name +"(" + attr.Name +")" + "   =   " + attr.Value + "\r\n";
                    }// foreach(var attr in element.Attributes().Reverse())

                }// if (element.HasAttributes) {

2
এটি খারাপ কারণ .Reverse()প্রকৃতপক্ষে তালিকাটি সংশোধন করছে।
কলিন বাসনেট

-8

এটি বেশ ভাল কাজ করে

List<string> list = new List<string>();

list.Add("Hello");
list.Add("Who");
list.Add("Are");
list.Add("You");

foreach (String s in list)
{
    Console.WriteLine(list[list.Count - list.IndexOf(s) - 1]);
}

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