এই সমস্যার জন্য আমি যে সমাধানটি ব্যবহার করি তা আরও বিস্তৃত।
আমার ব্যবহারের স্ট্যাটিক শ্রেণিতে একটি এক্সটেনশন পদ্ধতি রয়েছে MarkEnd
যা T
-items ইন EndMarkedItem<T>
-াইটেমগুলিতে রূপান্তর করে । প্রতিটি উপাদান অতিরিক্ত দিয়ে চিহ্নিত int
করা হয়, যা হয় 0 ; বা (বিশেষত একশেষে শেষ 3 টি আইটেমের প্রতি আগ্রহী) -3 , -2 , বা -1 সর্বশেষ 3 টি আইটেমের জন্য।
এটি নিজস্বভাবে দরকারী হতে পারে, উদাহরণস্বরূপ যখন আপনি foreach
শেষ 2 ব্যতীত প্রতিটি উপাদান বাদে কমা দিয়ে একটি সহজ- লুপে একটি তালিকা তৈরি করতে চান , দ্বিতীয় থেকে শেষ আইটেমের পরে একটি সংমিশ্রণ শব্দ থাকে (যেমন " এবং " বা " বা ") এবং শেষ উপাদানটি পরে বিন্দু by
গত ছাড়া সমগ্র তালিকা জেনারেট করার জন্য এন আইটেম, এক্সটেনশন পদ্ধতি ButLast
কেবল উপর iterates EndMarkedItem<T>
গুলি যখন EndMark == 0
।
আপনি যদি নির্দিষ্ট না করে থাকেন তবে tailLength
কেবলমাত্র শেষ আইটেমটি চিহ্নিত (ইন MarkEnd()
) বা ড্রপ (ইন ButLast()
) হয়।
অন্যান্য সমাধানগুলির মতো, এটি বাফার করে কাজ করে।
using System;
using System.Collections.Generic;
using System.Linq;
namespace Adhemar.Util.Linq {
public struct EndMarkedItem<T> {
public T Item { get; private set; }
public int EndMark { get; private set; }
public EndMarkedItem(T item, int endMark) : this() {
Item = item;
EndMark = endMark;
}
}
public static class TailEnumerables {
public static IEnumerable<T> ButLast<T>(this IEnumerable<T> ts) {
return ts.ButLast(1);
}
public static IEnumerable<T> ButLast<T>(this IEnumerable<T> ts, int tailLength) {
return ts.MarkEnd(tailLength).TakeWhile(te => te.EndMark == 0).Select(te => te.Item);
}
public static IEnumerable<EndMarkedItem<T>> MarkEnd<T>(this IEnumerable<T> ts) {
return ts.MarkEnd(1);
}
public static IEnumerable<EndMarkedItem<T>> MarkEnd<T>(this IEnumerable<T> ts, int tailLength) {
if (tailLength < 0) {
throw new ArgumentOutOfRangeException("tailLength");
}
else if (tailLength == 0) {
foreach (var t in ts) {
yield return new EndMarkedItem<T>(t, 0);
}
}
else {
var buffer = new T[tailLength];
var index = -buffer.Length;
foreach (var t in ts) {
if (index < 0) {
buffer[buffer.Length + index] = t;
index++;
}
else {
yield return new EndMarkedItem<T>(buffer[index], 0);
buffer[index] = t;
index++;
if (index == buffer.Length) {
index = 0;
}
}
}
if (index >= 0) {
for (var i = index; i < buffer.Length; i++) {
yield return new EndMarkedItem<T>(buffer[i], i - buffer.Length - index);
}
for (var j = 0; j < index; j++) {
yield return new EndMarkedItem<T>(buffer[j], j - index);
}
}
else {
for (var k = 0; k < buffer.Length + index; k++) {
yield return new EndMarkedItem<T>(buffer[k], k - buffer.Length - index);
}
}
}
}
}
}