What is the fastest way to add a new item to an existing array?
Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4
(I already know that when working with dynamic list of items you should rather use a List
, ArrayList
or similar IEnumerables
. But what to do if you're stuck to legacy code that uses arrays?)
What I've tried so far:
' A) converting to List, add item and convert back
Dim list As List(Of Integer)(arr)
list.Add(newItem)
arr = list.ToArray()
' --> duration for adding 100.000 items: 33270 msec
' B) redim array and add item
ReDim Preserve arr(arr.Length)
arr(arr.Length - 1) = newItem
' --> duration for adding 100.000 items: 9237 msec
' C) using Array.Resize
Array.Resize(arr, arr.Length + 1)
arr(arr.Length - 1) = newItem
' --> duration for adding 100.000 items: 1 msec
' --> duration for adding 100.000.000 items: 1168 msec
A) seems very slow since every time an item is added two conversions of the whole array are done. B) seems faster but still the array is copied once during the ReDim Preserve
. C) seems to be the fastest at this point. Is there anything better?
Case C) is the fastest. Having this as an extension:
Public Module MyExtensions
<Extension()> _
Public Sub Add(Of T)(ByRef arr As T(), item As T)
Array.Resize(arr, arr.Length + 1)
arr(arr.Length - 1) = item
End Sub
End Module
Usage:
Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4
arr.Add(newItem)
' --> duration for adding 100.000 items: 1 msec
' --> duration for adding 100.000.000 items: 1168 msec
For those who didn't know what next, just add new module file and put @jor code (with my little hacked, supporting 'nothing' array) below.
Module ArrayExtension
<Extension()> _
Public Sub Add(Of T)(ByRef arr As T(), item As T)
If arr IsNot Nothing Then
Array.Resize(arr, arr.Length + 1)
arr(arr.Length - 1) = item
Else
ReDim arr(0)
arr(0) = item
End If
End Sub
End Module
Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4
ReDim Preserve arr (3)
arr(3)=newItem
for more info Redim
Not very clean but it works :)
Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4
arr = arr.Concat({newItem}).ToArray
It depends on how often you insert or read. You can increase the array by more than one if needed.
numberOfItems = ??
' ...
If numberOfItems+1 >= arr.Length Then
Array.Resize(arr, arr.Length + 10)
End If
arr(numberOfItems) = newItem
numberOfItems += 1
Also for A, you only need to get the array if needed.
Dim list As List(Of Integer)(arr) ' Do this only once, keep a reference to the list
' If you create a new List everything you add an item then this will never be fast
'...
list.Add(newItem)
arrayWasModified = True
' ...
Function GetArray()
If arrayWasModified Then
arr = list.ToArray()
End If
Return Arr
End Function
If you have the time, I suggest you convert it all to List and remove arrays.
* My code might not compile