32

In the C++ Standard Template Library (STL), it is possible for example to create a vector consisting of multiple copies of the same element, using this constructor:

std::vector<double> v(10, 2.0);

This would create a vector of 10 doubles, initially set to 2.0.

I want to do a similar thing in C#, more specifically creating an array of n doubles with all elements initialized to the same value x.

I have come up with the following one-liner, relying on generic collections and LINQ:

double[] v = new double[n].Select(item => x).ToArray();

However, if an outsider would read this code I don't think it would be immediately apparent what the code actually does. I am also concerned about the performance, I suppose it would be faster to initialize the array elements via a for loop (although I haven't checked). Does anybody know of a cleaner and/or more efficient way to perform this task?

Anders Gustafsson
  • 15,837
  • 8
  • 56
  • 114
  • [Extension constructors](http://stackoverflow.com/questions/4782034/is-it-possible-to-create-constructor-extension-method-how) would be great for such usage scenarios. – SWeko Sep 05 '11 at 13:21

6 Answers6

49

What about this?

double[] v = Enumerable.Repeat(x, n).ToArray();

EDIT: I just did a small benchmark; to create 1000 arrays of 100000 elements each, using a loop is about 3 times faster that Enumerable.Repeat.

Repeat 
00:00:18.6875488 

Loop 
00:00:06.1628806 

So if performance is critical, you should prefer the loop.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • Thanks, Thomas, the Enumerable.Repeat method was new to me. Thanks also for the benchmark; I did the same thing myself just now out of curiosity, and reached about the same conclusion. – Anders Gustafsson Sep 05 '11 at 13:30
  • @Thomas @Anders: The `ToArray` first creates a `List`, then fills it and then creates the final array using the size of the List. This is probably the reason why it's so much slower (and why if possible I prefer to use the `ToList` instead of the `ToArray`) – xanatos Sep 05 '11 at 20:22
  • 1
    @xanatos, no, it's not what `ToArray` does; look at the implementation with Reflector or another decompiler... The problem is that the number of elements is not known initially, so it starts with a small array, fills it, creates a bigger array and copy the items from the smaller one, fills the bigger array, etc. It involves a lot of array creation and copy, which is why it's so slow. And ToArray is not noticeably slower that ToList... actually they probably have roughly the same performance characteristics – Thomas Levesque Sep 05 '11 at 21:30
  • @Thomas While technically it internally uses a structure called `Buffer`, if the source isn't a `ICollection` the `Buffer` works exactly as I've said. Look at the `Buffer` Constructor and to the `Buffer.ToArray` – xanatos Sep 06 '11 at 04:38
  • @xanatos, I just checked again; there's no trace of a `List` in the `Buffer` structure... – Thomas Levesque Sep 06 '11 at 08:43
  • @Thomas I haven't said that `Buffer` USES a `List` but its internal working are equal. Minimum size = 4, increase size = doubling. So at first it builds an array of 4 elements, if he needs more space it goes forward doubling (exactly as a `List`). In the end the `Buffer.ToArray` looks if his array has the EXACT right size then it can return directly it (and in this case the speed of ToList and of ToArray would be nearly equal. Same number and type of operations. Same number of doubling at the same sizes). Otherwise it creates a copy of the array with the right size. – xanatos Sep 06 '11 at 08:50
  • @xanatos, OK, I misunderstood your first comment, because you said that it created a `List`... since it was marked as code, I thought you were referring to the actual `List` class. – Thomas Levesque Sep 06 '11 at 09:24
  • @Thomas In the end the time differences aren't much, and for primitive types `ToArray` wins. For reference types `ToList` is a little faster. Over 65k elements `ToList` wins very often, but how many arrays so big you handle? It IS premature optimization, but they are nearly equivalent in the result and so I can choose :-). An example benchmark http://pastebin.com/PDRHDT3G – xanatos Sep 06 '11 at 09:28
9
var arr = Enumerable.Repeat(x, n).ToArray();

Personally, I'd just use a regular array loop, though:

var arr = new double[n];
for(int i = 0 ; i < arr.Length ; i++) arr[i] = x;

More characters, but the array is demonstrably the right size from the outset - no iterative growth List<T>-style and final copy back. Also; simply more direct - and the JIT can do a lot to optimise the for(int i = 0 ; i < arr.Length ; i++) pattern (for arrays).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks, Mark, I was not aware of Enumerable.Repeat. And yes, as also pointed out by Thomas, the for loop seem to give the best performance. – Anders Gustafsson Sep 05 '11 at 13:30
3

Later versions of .NET have introduced an Array.Fill method. See usage:

double[] v = new double[n];
Array.Fill(v, 2.0);
Cole Cameron
  • 2,213
  • 1
  • 13
  • 12
2
double[] theSameValues = Enumerable.Repeat(2.0, 10).ToArray();
sll
  • 61,540
  • 22
  • 104
  • 156
-1

the for each (or better the classic for) is always much faster than using Linq. You should use the Linq expression only if it makes the code more readable

Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70
  • Thanks, Massimiliano. Yes, it was quite apparent when I did my own benchmarking that the for loop is preferable from a performance point-of-view. In the end, this is probably where I will land. – Anders Gustafsson Sep 05 '11 at 13:34
-2

In VB.NET

Imports System.Linq

Dim n As Integer = 10

Dim colorArray = New Color(n - 1) {}.[Select](Function(item) Color.White).ToArray()