[英]How to make a collection be “n” elements long using extension methods?
所以,這是我的問題,我有一個給定的對象,它是一個IEnumerable,我保證所說的集合總是最多有4個元素。 現在,由於一個不重要的原因,我希望能夠以一種優雅的方式“強制”該集合包含4個元素(如果它沒有更少)。
我已經完成了一些研究,而且最令人信服的候選人是Zip,但它在收到最短的收集結束后就會停止拉鏈。
有沒有辦法在沒有自己的擴展方法的情況下這樣做? 為了更好地解釋自己:
var list1 = new List<Dog> {
new Dog { Name = "Puppy" }
}
var list2 = new List<Dog> {
new Dog { Name = "Puppy1" },
new Dog { Name = "Puppy2" },
new Dog { Name = "Puppy3" },
new Dog { Name = "Puppy4" },
}
var other1 = list1.ExtendToNElements(4).ToList();
//Now other1's first element is an instance of Dog with Name = "Puppy"
//And the following 3 elements are null, or have a Dog with no name
//I don't really care about that
var other2 = list2.ExtendToNElements(4).ToList();
//other2 is the same as list2, nothing got added.
提前致謝!
快速單行(應該算作“沒有擴展方法可行”):
public static IEnumerable<TItem> Extend<TItem>(
this IEnumerable<TItem> source,
int n)
{
return source.Concat(Enumerable.Repeat(default(TItem), n))
.Take(n);
}
由於Repeat
采用顯式計數,因此傳入n
給出了合理的上限。 無論如何,元素都是按需生成的。 使用source.Count()
會強制執行不理想的source
。
稍微過度設計和靈活的版本:
public static IEnumerable<TItem> Extend<TItem>(
this IEnumerable<TItem> source,
int n,
Func<TItem> with)
{
return source.Concat(
from i in Enumerable.Range(0, n) select with()
).Take(n);
}
public static IEnumerable<TItem> Extend<TItem>(
this IEnumerable<TItem> source,
int n,
TItem with = default(TItem))
{
return source.Extend(n, with: () => with);
}
您可以使用MoreLinq的Pad方法: http : //code.google.com/p/morelinq/ (NuGet: http ://www.nuget.org/packages/morelinq)
這將附加類型的默認值(在本例中為null
):
var other1 = list1.Pad(4).ToList();
或者,如果要提供默認值:
var other1 = list1.Pad(4, "Puppy_null").ToList();
或者如果你想要那些編號的小狗:
var other1 = list.Pad(4, (count) => "Puppy" + count).ToList();
如果Pad
方法的長度已經等於或大於您的焊盤尺寸,則Pad
方法不會添加其他條目。
如果你想在不引入整個項目的情況下整合/改編它,那么這就是Pad
實現: http : //code.google.com/p/morelinq/source/browse/MoreLinq/Pad.cs
class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
list.Capacity = 4;
var items = list.TakeOrDefault(4);
}
}
public static class EnumerableExtensions
{
public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> enumerable, int length)
{
int count = 0;
foreach (T element in enumerable)
{
if (count == length)
yield break;
yield return element;
count++;
}
while (count != length)
{
yield return default(T);
count++;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.