Самый быстрый способ добавить элемент в массив

каков самый быстрый способ добавить новый элемент в существующий массив?

Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4

(Я уже знаю, что при работе с динамическим списком предметов, которые вы должны использовать List, ArrayList или подобное IEnumerables. Но что делать, если вы застряли в устаревшем коде, который использует массивы?)

что я пробовал до сих пор:

' 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) кажется очень медленным, так как каждый раз, когда добавляется элемент, выполняются два преобразования всего массива. B) кажется быстрее, но все же массив скопировано один раз во время ReDim Preserve. C) на данный момент, кажется, самый быстрый. Есть что-нибудь получше?

5 ответов


случай C) самый быстрый. Имея это как расширение:

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

использование:

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

для тех, кто не знал, что дальше, просто добавьте новый файл модуля и поместите @jor-код (с моим маленьким взломанным, поддерживающим массив "ничего") ниже.

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

дополнительная информация вместо


Не очень чистый, но это работает :)

Dim arr As Integer() = {1, 2, 3}
Dim newItem As Integer = 4

arr = arr.Concat({newItem}).ToArray

Это зависит от того, как часто вы вставляете или читать. При необходимости можно увеличить массив более чем на один.

numberOfItems = ??

' ...

If numberOfItems+1 >= arr.Length Then
    Array.Resize(arr, arr.Length + 10)
End If

arr(numberOfItems) = newItem
numberOfItems += 1

также для A вам нужно только получить массив, если это необходимо.

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

Если у вас есть время, я предлагаю вам преобразовать все это в список и удаление массивов.

* мой код может не компилироваться