How to make a collection with long n elements using extension methods?

So, here is my problem, I have this object, which is IEnumerable, and I am guaranteed that there will always be no more than 4 elements in this collection. Now, for some reason, which is not important, I would like, for some elegant way, to "force" the collection to contain 4 elements, if it is less.

I've already done some research, and the most compelling candidate is Zip, but it stops after it reaches the shortest end of the collection.

Is there a way to do this without my own extension method? To better explain yourself:

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 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. 

Thanks in advance!

+4
source share
3 answers

Fast one-line (which should be considered "doable without extension method"):

 public static IEnumerable<TItem> Extend<TItem>( this IEnumerable<TItem> source, int n) { return source.Concat(Enumerable.Repeat(default(TItem), n)) .Take(n); } 

Since Repeat takes an explicit count, passing in n gives a reasonable upper bound. In any case, elements are generated on demand. Using source.Count() will force the execution of source , which is not ideal.

A slightly more redesigned and flexible version:

 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); } 
+4
source

You can use the MoreLinq Pad method: http://code.google.com/p/morelinq/ (NuGet: http://www.nuget.org/packages/morelinq )

In this case, the default value for the ( null ) type will be added:

 var other1 = list1.Pad(4).ToList(); 

Or if you want to specify a default value:

 var other1 = list1.Pad(4, "Puppy_null").ToList(); 

Or if you want to have these numbered puppies:

 var other1 = list.Pad(4, (count) => "Puppy" + count).ToList(); 

The Pad method will not add additional entries if its length is already equal to or greater than your pad size.

Here's the implementation of Pad specifically if you want to enable / adapt it without involving the whole project: http://code.google.com/p/morelinq/source/browse/MoreLinq/Pad.cs

+3
source
  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++; } } } 
0
source

All Articles