Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

460
Views
C# Enumerable.Take with default value

What is the best way to get exactly x values from an Enumerable in C#. If i use Enumerable .Take() like this:

var myList = Enumerable.Range(0,10);
var result = myList.Take(20);

The result will only have 10 elements.

I want to fill the missing entries with a default value. Something like this:

var myList = Enumerable.Range(0,10);
var result = myList.TakeOrDefault(20, default(int));  //Is there anything like this?

Is there such a function in C# and if not, what would be the best way to achieve this?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You could do something like:

var result = myList.Concat(Enumerable.Repeat(default(int), 20)).Take(20); 

And it would be easy to turn this into an extension method:

public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, T defaultValue)
{
    return  list.Concat(Enumerable.Repeat(defaultValue, count)).Take(count);
}

But there is a subtle gotcha here. This would work perfectly fine for value types, for a reference type, if your defaultValue isn't null, you are adding the same object multiple times. Which probably isn't want you want. For example, if you had this:

var result = myList.TakeOrDefault(20, new Foo());

You are going to add the same instance of Foo to pad your collection. To solve that problem, you'd need something like this:

public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> list, int count, Func<T> defaultFactory)
{
    return  list.Concat(Enumerable.Range(0, count).Select(i => defaultFactory())).Take(count);
}

Which you'd call like this:

var result = myList.TakeOrDefault(20, () => new Foo())

Of course, both methods can co-exist, so you could easily have:

// pad a list of ints with zeroes
var intResult = myIntList.TakeOrDefault(20, default(int));
// pad a list of objects with null
var objNullResult = myObjList.TakeOrDefault(20, (object)null);
// pad a list of Foo with new (separate) instances of Foo
var objPadNewResult = myFooList.TakeOrDefault(20, () => new Foo());
over 4 years ago · Santiago Trujillo Report

0

Its not there by default, but it's easy enough to write as an extension method

public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> items, int count, T defaultValue)
{
    var i = 0;
    foreach(var item in items)
    {
        i++;
        yield return item;
        if(i == count)
             yield break;
    }
    while(i++<count)
    {
        yield return defaultValue;
    }
}

Live example: http://rextester.com/XANF91263

over 4 years ago · Santiago Trujillo Report

0

What you're looking for is a general-purpose PadTo method, which extends the collection's length if needed using a given value.

public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len)
{
    return source.PadTo(len, default(T));
}

public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len, T elem)
{
    return source.PadTo(len, () => elem);
}

public static IEnumerable<T> PadTo<T>(this IEnumerable<T> source, int len, Func<T> elem)
{
    int i = 0;
    foreach(var t in source)
    {
        i++;
        yield return t;
    }

    while(i++ < len)
        yield return elem();
}

You can now express:

myList.Take(20).PadTo(20);

This is analogous to Scala's List[A].padTo

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!