2013-08-07 16 views
20

Jaki jest najszybszy sposób dodania nowego elementu do istniejącej macierzy?Najszybszy sposób dodawania elementu do tablicy

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

(już wiem, że podczas pracy z dynamicznej listy elementów należy raczej używać List, ArrayList lub podobny IEnumerables. Ale co zrobić, gdy utkniesz do starszych kod, który używa tablic?)

Co próbowałem dotąd:

' 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) wydaje się bardzo powolny, ponieważ za każdym razem element jest dodawany dwie konwersje całej tablicy są zrobione. B) wydaje się szybszy, ale nadal tablica jest kopiowana jeden raz podczas ReDim Preserve. C) wydaje się być najszybszy w tym momencie. Czy jest coś lepszego?

+0

Z szacunkiem, myślę, że jesteś porównywanie jabłek z mango: nikt nie będzie kiedykolwiek używać pierwszą alternatywę. Jedną z zalet listy jest to, jak szybko możesz dodawać do niej nowe elementy (jeśli nie wykonasz konwersji do tablicy, po prostu dodaj element, zobaczysz, że jest znacznie szybszy niż jakakolwiek inna alternatywa): jeśli są zainteresowani jedynie szybkim dodawaniem elementów, korzystaniem z listy (w ogóle nie polegaj na tablicy). Również lista pozwala znacznie więcej opcji do sprawdzenia/indeksowania swoich elementów, niż pozwalają na to tablice. ALE inne niż to, w czystej wydajności (na przykład w pętlach) są znacznie gorsze ... – varocarbas

+3

Podsumowanie: używaj tablic i list w najlepszych sytuacjach. Chociaż VB.NET pozwala na rediminację, to nie jest to, czego oczekuje się od macierzy: tablice zapewniają najlepszą wydajność w warunkach o stałych rozmiarach, po prostu powtarzają się w swoich elementach. Z drugiej strony Listy są przeznaczone do mniej iteracyjnego traktowania: mniejszej liczby elementów, regularnych zmian wymiarów, fantazyjnych zapytań w celu uzyskania dostępu do elementów itd. Wszystkie te funkcje są funkcjami, których tablice nie są tak dobre. Tak więc, tablice dla wydajności w warunkach o stałych rozmiarach; Listy zmieniających się warunków. – varocarbas

+0

PS: Listy są również mniej wydajne pod względem pamięci. – varocarbas

Odpowiedz

33

sprawie C) jest najszybszy. Mając to jako rozszerzenie:

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 

Zastosowanie:

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 
+0

powinien to być Array.Resize (arr, arr.Length + 1) próbowałem. –

+0

@JimThio: masz rację - dziękuję! Zaktualizowałem fragment kodu. – jor

+0

Dla tych, którzy nie wiedzieli, co dalej, po prostu dodaj nowy plik modułu i dodaj kod @jor (z moją małą zhackowaną, obsługującą tablicę "nic") poniżej. + ---- Edytowany, kod pomieszany. Zobacz moją odpowiedź poniżej. –

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

uzyskać więcej informacji Redim

+4

Z technicznego punktu widzenia powinieneś napisać: ReDim Zachowaj arr (3), w przeciwnym razie przewymiarujesz tablicę o 1. Ja osobiście nie zbytnio się o to troszczę (nadmiernie wymieniam tablice jeden za każdym razem), ale myślę, że byłaby to bardziej właściwa odpowiedź. – varocarbas

+0

tablica została zainicjalizowana 3 elementami i chce dodać jeszcze jeden element, więc rozmiar powinien wynosić 4, czyż nie? –

+1

Tak, ale ReDim Zachowaj arr (4) nie wskazuje wielkości 4, ale najwyższego indeksu 4, czyli wielkości 5. Jak powiedziałem, nie powinienem dawać lekcji na tym froncie, o ile jestem zawsze robiąc to, co robisz, ale, teoretycznie rzecz biorąc, nie jest prawidłowe. – varocarbas

0

To zależy od tego, jak często wkładać ani czytać. W razie potrzeby możesz zwiększyć tablicę o więcej niż jeden.

Również w przypadku A, w razie potrzeby wystarczy uzyskać tablicę.

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 

Jeśli masz czas, proponuję przekonwertować go na listę i usunąć tablice.

* Mój kod nie może skompilować

8

Dla tych, którzy nie wiedzą, co dalej, po prostu dodać nowy plik modułu i umieścić @jor kod (z moją małą Hacked, wspieranie " nic "tablicy" poniżej.

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 
4

Nie bardzo czyste, ale to działa :)

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

arr = arr.Concat({newItem}).ToArray 
Powiązane problemy