আপনি বেশ কয়েকটি ক্যোয়ারী ব্যবহার করতে পারেন যা ব্যবহার করে Take
এবং Skip
তবে এটি মূল তালিকায় অনেকগুলি পুনরাবৃত্তি যুক্ত করবে, আমি বিশ্বাস করি।
বরং আমি মনে করি আপনার নিজের মতো করে একটি পুনরুক্তি তৈরি করা উচিত:
public static IEnumerable<IEnumerable<T>> GetEnumerableOfEnumerables<T>(
IEnumerable<T> enumerable, int groupSize)
{
// The list to return.
List<T> list = new List<T>(groupSize);
// Cycle through all of the items.
foreach (T item in enumerable)
{
// Add the item.
list.Add(item);
// If the list has the number of elements, return that.
if (list.Count == groupSize)
{
// Return the list.
yield return list;
// Set the list to a new list.
list = new List<T>(groupSize);
}
}
// Return the remainder if there is any,
if (list.Count != 0)
{
// Return the list.
yield return list;
}
}
তারপরে আপনি এটিকে কল করতে পারেন এবং এটি লিনকিউ সক্ষম হয়েছে যাতে ফলস্বরূপ ক্রমগুলির উপর আপনি অন্যান্য ক্রিয়াকলাপ করতে পারেন।
স্যামের উত্তরের আলোকে , আমি অনুভব করেছি যে এটি করা ছাড়া আরও সহজ উপায় ছিল:
- আবার তালিকার মাধ্যমে আইট্রেট করা (যা আমি মূলত করিনি)
- অংশগুলি প্রকাশের আগে দলগুলিতে আইটেমগুলিকে ধাতবকরণ (বড় আকারের আইটেমগুলির জন্য, মেমরির সমস্যা থাকবে)
- স্যাম পোস্ট করা সমস্ত কোড
তাই বলা হয়, এখানে অন্য পাস, যা আমি করতে একটি এক্সটেনশন পদ্ধতিতে বিধিবদ্ধ করেছি IEnumerable<T>
নামক Chunk
:
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source,
int chunkSize)
{
// Validate parameters.
if (source == null) throw new ArgumentNullException("source");
if (chunkSize <= 0) throw new ArgumentOutOfRangeException("chunkSize",
"The chunkSize parameter must be a positive value.");
// Call the internal implementation.
return source.ChunkInternal(chunkSize);
}
সেখানে অবাক করার মতো কিছু নেই, কেবলমাত্র বেসিক ত্রুটি পরীক্ষা করা।
এতে চলেছেন ChunkInternal
:
private static IEnumerable<IEnumerable<T>> ChunkInternal<T>(
this IEnumerable<T> source, int chunkSize)
{
// Validate parameters.
Debug.Assert(source != null);
Debug.Assert(chunkSize > 0);
// Get the enumerator. Dispose of when done.
using (IEnumerator<T> enumerator = source.GetEnumerator())
do
{
// Move to the next element. If there's nothing left
// then get out.
if (!enumerator.MoveNext()) yield break;
// Return the chunked sequence.
yield return ChunkSequence(enumerator, chunkSize);
} while (true);
}
মূলত, এটি পায় IEnumerator<T>
এবং প্রতিটি আইটেমের মাধ্যমে ম্যানুয়ালি পুনরাবৃত্তি হয়। এটি বর্তমানে কোনও আইটেম গণনা করতে হবে কিনা তা যাচাই করে। প্রতিটি খণ্ডটি গণনার পরে, যদি কোনও আইটেম বাকি না থাকে তবে তা বের হয়ে যায়।
ক্রমটিতে আইটেম রয়েছে তা সনাক্ত করার পরে এটি অভ্যন্তরীণ IEnumerable<T>
বাস্তবায়নের জন্য দায়বদ্ধ করে ChunkSequence
:
private static IEnumerable<T> ChunkSequence<T>(IEnumerator<T> enumerator,
int chunkSize)
{
// Validate parameters.
Debug.Assert(enumerator != null);
Debug.Assert(chunkSize > 0);
// The count.
int count = 0;
// There is at least one item. Yield and then continue.
do
{
// Yield the item.
yield return enumerator.Current;
} while (++count < chunkSize && enumerator.MoveNext());
}
যেহেতু MoveNext
ইতিমধ্যে IEnumerator<T>
পাস করার জন্য আহ্বান করা হয়েছিল ChunkSequence
, এটি আইটেমের চেয়ে ফিরে আসা আইটেমের ফলন দেয় Current
এবং তারপরে গণনা বৃদ্ধি করে, chunkSize
প্রতিটি আইট্রেশনের পরে আইটেমের চেয়ে বেশি আর কখনও ফিরে না আসার বিষয়টি নিশ্চিত করে (তবে সংখ্যায় সংক্ষিপ্ত বৃত্ত হলে সংক্ষিপ্তসার্কিটেড প্রাপ্ত আইটেমগুলি খণ্ড আকার ছাড়িয়েছে)।
যদি কোনও আইটেম বাকি না থাকে, তবে InternalChunk
পদ্ধতিটি বাইরের লুপে আবার একটি পাস করবে, কিন্তু যখন MoveNext
দ্বিতীয়বার বলা হয়, তখনও ডকুমেন্টেশন (জোর দেওয়া খনি) অনুসারে এটি মিথ্যা ফিরবে :
যদি মুভনেক্সট সংগ্রহের শেষ প্রান্তটি অতিক্রম করে তবে সংগ্রহের শেষ উপাদানটির পরে গণকের অবস্থান নির্ধারণ করা হবে এবং মুভ নেক্সট মিথ্যা প্রত্যাবর্তন করবে। যখন গণক এই অবস্থানে থাকে তখন মুভি নেক্সটে পরবর্তী কলগুলিও রিসেট না বলা পর্যন্ত মিথ্যা ফিরিয়ে দেয়।
এই মুহুর্তে, লুপটি ভেঙে যাবে এবং ক্রমগুলির ক্রমটি শেষ হবে।
এটি একটি সহজ পরীক্ষা:
static void Main()
{
string s = "agewpsqfxyimc";
int count = 0;
// Group by three.
foreach (IEnumerable<char> g in s.Chunk(3))
{
// Print out the group.
Console.Write("Group: {0} - ", ++count);
// Print the items.
foreach (char c in g)
{
// Print the item.
Console.Write(c + ", ");
}
// Finish the line.
Console.WriteLine();
}
}
আউটপুট:
Group: 1 - a, g, e,
Group: 2 - w, p, s,
Group: 3 - q, f, x,
Group: 4 - y, i, m,
Group: 5 - c,
একটি গুরুত্বপূর্ণ দ্রষ্টব্য, আপনি যদি পুরো সন্তানের ক্রমটি নিকাশ না করেন বা পিতামাতার ক্রমের কোনও বিন্দুতে ভাঙ্গেন না তবে এটি কাজ করবে না । এটি একটি গুরুত্বপূর্ণ সতর্কীকরণ, কিন্তু যদি আপনার ব্যবহার কেস যে আপনার গ্রাস করবে যে সিকোয়েন্সগুলির ক্রমের উপাদান তবে এটি আপনার পক্ষে কাজ করবে।
অতিরিক্তভাবে, আপনি যদি অর্ডার নিয়ে খেলেন তবে এটি অদ্ভুত জিনিসগুলি করবে, যেমন স্যামের এক পর্যায়ে হয়েছিল ।