7
\$\begingroup\$

I want to add a value multiple times at the beginning of a list, what I have is...

internal static class Helper
{
  public static void Prepend(this IList<double> source, double value, int count)
  {
    for (var i = 0; i < count; ++i)
    {
      source.Insert( 0, value );
    }
  }
}

Then use it as follow

// create
var mylist = new List(){ ... };  // create the list
mylist.Prepend( 0, 10 );  // prepend 0 to the list

But I wonder if there isn't a more efficient way of doing the same thing?

\$\endgroup\$
1
  • \$\begingroup\$ If count is greater than source then it might be more efficient to append the source to the count \$\endgroup\$
    – paparazzo
    Jun 9, 2017 at 15:26

2 Answers 2

8
\$\begingroup\$

Is there a reason you use IList? because List has the InsertRange method which uses Array.Copy amongst other optimizations.

If we need to support IList, we don't want to depend upon implementation details and IList.Insert sounds like your best option.

Another approach is you could check whether the actual implementation is List and use the InsertRange method or fallback to Insert in a loop.

Example of adding the items using InsertRange

var items = Enumerable.Repeat(0, 10);
source.InsertRange(0, items);
\$\endgroup\$
4
  • \$\begingroup\$ Yes, it could be a List, but I am not sure I understand InsertRange, I would I be able to add 'x' numbers at the beginning of the list using InsertRange? \$\endgroup\$ Jun 9, 2017 at 13:03
  • \$\begingroup\$ @SimonGoodman no, it allows you to add a range of values in one call. Therefore, you should build your list of duplicate value first. I have updated the answer with an example. \$\endgroup\$
    – Myrtle
    Jun 9, 2017 at 13:04
  • \$\begingroup\$ @Paparazzi it is, otherwise the .NET implementation would not use Array.Copy and use the the for loop as fallback. \$\endgroup\$
    – Myrtle
    Jun 9, 2017 at 13:14
  • 2
    \$\begingroup\$ I see now, I didn't know about the Enumerable.Repeat, that's why I wasn't sure how InsertRange would work in that case. \$\endgroup\$ Jun 9, 2017 at 13:30
3
\$\begingroup\$

If you don't care about performance the most generic solution would be to use Concat and not to modify the original list at all. Usually you don't want to do it but return a new collection instead.

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T value, int count)
{
    return Enumerable.Repeat(value, count).Concat(source);
}

var mylist = new List(){ ... };  // create the list

If you really create a list and prepend more items to it right away in the next step then combinding the the constructor with the collection initializer is another option that might work for you:

var result = new List<int>(Enumerable.Repeat(0, 10)) { 2, 3, 4 };
\$\endgroup\$
2
  • 4
    \$\begingroup\$ Important to consider difference between IEnumerable<T> and List<T>. I would expect an extension method on the former to return a new IEnumerable<T> and would expect the latter to mutate the List<T> instance. \$\endgroup\$
    – RobH
    Jun 9, 2017 at 14:32
  • \$\begingroup\$ @t3chb0t thanks, to answer your question, the list is created much earlier in the process. \$\endgroup\$ Jun 10, 2017 at 6:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.