19

To create and initialize an array with another array I currently do this:

void Foo( int[] a )
{
    int[] b = new int[ a.Length ];
    for ( int i = 0; i < a.Length; ++i )
        b[ i ] = a[ i ];

    // Other code ...
}

Is there a shorter or more idiomatic way of doing this in C#?

It will be great if this can be done in a single statement, like in C++:

vector<int> b( a );

If this cannot be done in a single statement, I will take what I get :-)

Ashwin Nanjappa
  • 76,204
  • 83
  • 211
  • 292
  • 2
    Couldn't you just use `Array.Copy`? – M.Babcock Mar 29 '12 at 00:04
  • should be a way to copy all the memory directly...in C++ http://stackoverflow.com/questions/3902215/using-memcpy-to-copy-a-range-of-elements-from-an-array – T.T.T. Mar 29 '12 at 00:05
  • http://stackoverflow.com/questions/5655553/whats-the-most-efficient-way-to-copy-elements-of-a-c-sharp-multidimensional-arr – T.T.T. Mar 29 '12 at 00:08
  • http://stackoverflow.com/questions/5099604/c-any-faster-way-of-copying-arrays – T.T.T. Mar 29 '12 at 00:08
  • Tommy: My question is a bit different from those because I am looking for the equivalent of vector b( a ) from C++ in C# – Ashwin Nanjappa Mar 29 '12 at 00:11

6 Answers6

28

I like using LINQ for this:

int[] b = a.ToArray();

That being said, Array.Copy does have better performance, if this will be used in a tight loop, etc:

int[] b = new int[a.Length];
Array.Copy(a, b, a.Length);

Edit:

It will be great if this can be done in a single statement, like in C++:

vector b( a );

The C# version of this would be:

List<int> b = new List<int>(a);

List<T> is C#'s equivalent to std::vector<T>. The constructor above works with any IEnumerable<T>, including another List<T>, an array (T[]), etc.

Community
  • 1
  • 1
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
7

Use Array.Copy to copy an array

     int[] source = new int[5];
     int[] target = new int[5];
     Array.Copy(source, target, 5);
Emmanuel N
  • 7,350
  • 2
  • 26
  • 36
3

Clone() and ToArray() are syntactically nice because you don't need to pre-allocate a destination array, but in terms of performance, Array.Copy() is the fastest method (see caveat below).

The reason for Array.Copy() being so fast is that it doesn't allocate any memory. However, if you require your arrays to be copied to a new region of memory each time, then Array.Copy() is no longer the fastest method.

Here are my performance results:

Copy: 0 ms
Copy (with allocation): 449 ms
Clone: 323 ms
ToArray: 344 ms

And here's the code I used:

const int arrayLength = 100000;
const int numberCopies = 1000;
var a = new int[arrayLength];
var b = new int[arrayLength];

var stopwatch = new Stopwatch();
for (var i = 0; i < numberCopies; i++) {
    Array.Copy(a, b, arrayLength);
}
Console.WriteLine($"Copy: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    var c = new int[arrayLength];
    Array.Copy(a, c, arrayLength);
}
Console.WriteLine($"Copy (with allocation): {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    b = (int[]) a.Clone();
}
Console.WriteLine($"Clone: {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
    b = a.ToArray();
}
Console.WriteLine($"ToArray: {stopwatch.ElapsedMilliseconds} ms");
DinoM
  • 144
  • 1
  • 4
1

Also try the default Clone() function which is implemented from the IClonable interface.

int[] b = a.Clone() as int[];
Kamrul
  • 324
  • 2
  • 8
0

You can achieve this easily by creating new empty array or you can use the given array.

int[] arr = { 1, 2, 0, 3, 4, 5, 0, 6, 0, 7, 8, 9, 0 };
int[] newArray = new int[arr.Length];

Array.Copy(arr, newArray, arr.Length);

foreach (var item in newArray)
{
   if(item != 0)
   Console.WriteLine(item);
}   
0

This solution is by no way the fastest nor the most elegant, but if you need to either skip some of the elements from the original array, or perhaps transform them you could do this with Linq

var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Select(s => s).ToArray();

// targetArray now contains 1,2,3,4,5,6,7,8,9

Admitted, that looks a bit stupid, unless you need to perform some kind of operation during copying

var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Skip(1).Take(3).Select(s => s*s+4).ToArray();

// targetArray now contains 8,13,20
MikNiller
  • 1,242
  • 11
  • 17