আমি জানি আমি একটি for
বিবৃতি ব্যবহার করতে এবং একই প্রভাব অর্জন করতে পারি, তবে আমি কি foreach
সি # এর লুপের সাহায্যে পিছনের দিকে লুপ করতে পারি ?
IEnumerable<int> Infinity() { int i = 1; while (true) yield return i++; }
আপনি কীভাবে এটি বিপরীত করবেন?
আমি জানি আমি একটি for
বিবৃতি ব্যবহার করতে এবং একই প্রভাব অর্জন করতে পারি, তবে আমি কি foreach
সি # এর লুপের সাহায্যে পিছনের দিকে লুপ করতে পারি ?
IEnumerable<int> Infinity() { int i = 1; while (true) yield return i++; }
আপনি কীভাবে এটি বিপরীত করবেন?
উত্তর:
একটি তালিকার সাথে কাজ করার সময় (সরাসরি সূচীকরণ), আপনি এটি ব্যবহারের মতো দক্ষতার সাথে এটি করতে পারবেন না for
লুপ ।
সম্পাদনা: যার অর্থ সাধারণত, আপনি যখন কোনও লুপ ব্যবহার করতে সক্ষম হন তখন for
সম্ভবত এই কাজের জন্য সঠিক পদ্ধতি। এছাড়াও, foreach
যথাযথভাবে কার্যকরভাবে প্রয়োগ করা হয়েছে, উপাদানগুলি সূচকগুলি এবং পুনরাবৃত্তির ক্রম থেকে পৃথক লুপগুলি প্রকাশের জন্য নিজেই তৈরি করা হয়েছে যা সমান্তরাল প্রোগ্রামিংয়ে বিশেষত গুরুত্বপূর্ণ । এটি আমার অভিমত যে আদেশের উপর নির্ভর করে পুনরাবৃত্তিটি foreach
লুপিংয়ের জন্য ব্যবহার করা উচিত নয় ।
yield return
" ব্যবহার করে ।
আপনি .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()
এক্সটেনশান পদ্ধতিটি আপনি যদি এমন একটি অনুভূতি খাওয়ান যা স্পষ্টভাবে ফুরিয়ে যাবে যা কখনই আইটেমগুলি ফিরিয়ে দেয় না।
যেমন 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";
}
}
আপনি যদি উল্টোদিকে পুনরাবৃত্তি করার চেষ্টা করেন তবে আপনি কী হওয়ার আশা করবেন?
foreach
পুনরাবৃত্তির জন্য ব্যবহার করার আগে , reverse
পদ্ধতিটি দ্বারা তালিকাটি বিপরীত করুন :
myList.Reverse();
foreach( List listItem in myList)
{
Console.WriteLine(listItem);
}
myList
হবে সে সম্পর্কে সতর্কতার একটি শব্দ সহায়ক। IEnumerable. বিপরীত এখানে কাজ করবে না।
myList
মনে হয় ধরণের System.Collections.Generic.List<System.Windows.Documents.List>
(বা অন্য কোনও কাস্টম List
টাইপ) অন্যথায় এই কোডটি কাজ করে না: পি
কখনও কখনও আপনার ইনডেক্সিংয়ের বিলাসিতা থাকে না বা সম্ভবত আপনি একটি লিনক ক্যোয়ারির ফলাফলগুলি বিপরীত করতে চান, বা সম্ভবত আপনি উত্স সংগ্রহটি সংশোধন করতে চান না, যদি এর মধ্যে কোনও সত্য হয় তবে লিনক আপনাকে সহায়তা করতে পারে।
লিনক অর্ডারবাইডিজেন্ডিংয়ের জন্য বাছাইকরণ কী সরবরাহ করতে লিনক সিলেক্ট সহ বেনামে টাইপ ব্যবহার করে একটি লিনক এক্সটেনশন পদ্ধতি;
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
আপনি যদি একটি তালিকা ব্যবহার করেন <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
আপনি যদি সংগ্রহের কোডটি পরিবর্তন করতে পারেন তবে এটি সম্ভব 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();
}
এর কারণে আপনার তালিকাটি আপনার তালিকার মাধ্যমে বিপরীত ক্রমে পুনরাবৃত্তি হবে।
কেবল একটি ইঙ্গিত: ডকুমেন্টেশনের মধ্যে আপনার তালিকাটির এই বিশেষ আচরণটি স্পষ্টভাবে বর্ণনা করা উচিত (স্ট্যাক বা কুইয়ের মতো স্ব-ব্যাখ্যাকারী শ্রেণীর নামটি বেছে নেওয়ার মাধ্যমে আরও ভাল)।
না। প্রতিটি আইটেমের জন্য সংগ্রহের মাধ্যমে প্রতিটি পুনরাবৃত্তি করে এবং অর্ডার নির্ভর করে এটি আইইনামেবল বা গেটইনুমেরেটর () ব্যবহার করে কিনা।
জন স্কিটির চমৎকার উত্তরের বিষয়ে কিছুটা বিশদভাবে বর্ণনা করা , এটি বহুমুখী হতে পারে:
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)) {
.
.
}
আমি এই কোডটি ব্যবহার করেছি যা কাজ করে
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) {
.Reverse()
প্রকৃতপক্ষে তালিকাটি সংশোধন করছে।
এটি বেশ ভাল কাজ করে
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]);
}