2

I am looking for fastest way to extend an array. No matter if only for length + 1 or length + x it has to be the most fastest way.

Here is an example:

var arr = new int [200];
for(int = 0; i < 200; i++)
   arr[i] = i;

And now I want to extend arr for 5 items beginning at index position 20.

var arr2 = new int [] { 999, 999, 999, 999, 999 }

How do I place arr2 inside arr by using most fast way in terms of performance?

The result shall look like this 0,1,2,3,4....20, 999, 999, 999, 999, 999, 21, 22, 23, 24....199

snowy hedgehog
  • 652
  • 1
  • 7
  • 23

6 Answers6

4

Create a new array which is the size you want, then use the static Array.Copy method to copy the original arrays into the new one.

You can't "extend" an array, you can only create a bigger one and copy the original into it.

Also, consider using List<int> or LinkedList<> instead of an array, unless you require extremely fine-grained control over what is in memory.

RobSiklos
  • 8,348
  • 5
  • 47
  • 77
  • all i care about is speed, i picked array since I though i might find the fastest way of inserting items in arrays instead lists plus i thought for some reason that lists are smart arrays and all i need is speed so picked the lowest level which is pure arrays. – snowy hedgehog Jun 05 '13 at 15:35
  • 3
    @snowyhedgehog By and large using lower level techniques will be slower than using higher level techniques unless you *really* know what you're doing. It's much easier to shoot yourself in the foot or use the tools improperly, thus resulting in much lower effectiveness, unless you're highly experienced using said tools. – Servy Jun 05 '13 at 15:37
  • If you are inserting often, it's better to use List or LinkedList. if you don't need to access by index (i.e. you're always iterating using foreach), LinkedList would probably give you the best performance benefit (at the cost of using more memory) – RobSiklos Jun 05 '13 at 15:38
  • @Jodrell: `Buffer.BlockCopy` is dangerous, since you need to provide byte offsets, not array indexes – RobSiklos Jun 05 '13 at 15:41
  • @RobSiklos but , it is significantly faster. – Jodrell Jun 05 '13 at 15:47
  • @Servy, agreed, and you need to test it. In many cases the high level functions use internal calls and compiler tricks you cannot directly access so you can't beat them. – Jodrell Jun 05 '13 at 15:48
  • 2
    @RobSiklos Generally not, actually. A `LinkedList` results in virtually zero memory locality, so you thrash your cache each time you iterate the list, resulting in it being *much* slower than iterating an array or list, in addition to using more memory. If you only need to be adding at the start or end then you'd probably want to use a `Stack` or `Queue` or a double ended queue if you need to add/remove to both ends. Those data structures will be implemented, under the hood, as arrays, to maintain memory locality. – Servy Jun 05 '13 at 15:50
  • A List is very often the fastest general purpose solution when you want to fire-and-forget. See "Performance Considerations" of the List documentation here: https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx – Graeme Wicksted Dec 18 '17 at 15:49
2

It is far easier to use List. But if you have to use arrays, you have to create new array of size 205 and copy values from both source arrays, since array size is constant.

ElmoVanKielmo
  • 10,907
  • 2
  • 32
  • 46
2

Your best bet is to use something like List<int> rather than an array. But if you must use an array:

int[] arr1 = new int[200];
// initialize array
int[] arr2 = new int[]{999, 999, 999, 999, 999};

int targetPos = 20;

// resizes the array, copying the items
Array.Resize(ref arr1, arr1.Length + arr2.Length);

// move the tail of the array down
Buffer.BlockCopy(arr1, 4*targetPos, arr1, 4*(targetPos+arr2.Length), 4*(arr1.Length - targetPos));

// copy arr2 to the proper position
Buffer.BlockCopy(arr2, 0, 4*arr1.targetPos, 4*arr2.Length);

It might be faster to create a new array and copy the items, like this.

int[] newArray = new int[arr1.Length + arr2.Length];

// copy first part of original array
Buffer.BlockCopy(arr1, 0, newArray, 0, 4*targetPos);

// copy second array
Buffer.BlockCopy(arr2, 0, newArray, 4*targetPos, 4*arr2.Length);

// copy remainder of original array
Buffer.blockCopy(arr1, 4*targetPos, newArray, 4*(targetPos + arr2.Length), 4*(arr1.Length - targetPos));

// and replace the original array
arr1 = newArray;

Which version is faster will depend on where targetPos is. The second version will be faster when targetPos is small. When targetPos is small, the first version has to copy a lot of data twice. The second version never copies more than it has to.

BlockCopy is kind of a pain to work with because it requires byte offsets, which is the reason for all the multiplications by four in the code. You might be better off using Array.Copy in the second version above. That will prevent you having to multiply everything by 4 (and forgetting sometimes).

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
1

If you know how long the array will be dimension it to that length,

var ints  = new int[someFixedLength];

If you have a vauge idea of the length, use a generic list.

var ints = new List<int>(someVagueLength);

both types implement IList but, the List type handles the redimensioning of the internal array is generically the "most fast" way.


Note: the initial .Count of the List will be 0 but, the internal array will be dimensioned to size you pass to to the constructor.


If you need to copy data between arrays, the quickest way is Buffer.BlockCopy, so from your example

Buffer.BlockCopy(arr2, 0, arr, sizeof(int) * 20, sizeof(int) * 5);

copies all 5 ints from arr2 into indecies 20, 21 ... 24 of arr.

there is no faster way to do this with c# (currently).

Jodrell
  • 34,946
  • 5
  • 87
  • 124
1

An answer showing timing benchmarks is given here: Best way to combine two or more byte arrays in C# . If you consider the "array you insert into " as arrays 1 and 3, and the "array to be inserted" as array 2, then the "concatenate three arrays" example applies directly.

Note the point at the end of the accepted answer: the method that is faster at creating yields an array that is slower to access (which is why I asked if you cared about speed to create, or access speed).

Community
  • 1
  • 1
Floris
  • 45,857
  • 6
  • 70
  • 122
0

using System.Linq you can do the following to extend an array by adding one new object to it...

int[] intA = new int[] { 1, 2, 3 };
int intB = 4;

intA = intA.Union(new int[] { intB }).ToArray();

...or you can extend an array by adding another array of items to it...

int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };

intA = intA.Union(intB).ToArray();

...or if you don't care about duplicates...

int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };

intA = intA.Concat(intB).ToArray();
Jim Roton
  • 1
  • 2