2013-07-06 12 views
5

Chciałem zapytać, jak wyciąć tablicę bez użycia Array.Copy. Dam wam przykład tego, co chcę osiągnąć, abyście mogli mnie zrozumieć.Poprawny formularz do plasterka tablicy w języku C#

Załóżmy, że mam tę tablicę. nazwany Oryginał

[1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15]

chcę uzyskać tablicę kopii z indeksu początkowego danego niektórych długości, powiedzmy chcę jeden element do elementu 6 chcę kod do wykonywania zadań, takich jak

int startIndex = 0; 
int lenght= 5; 
int[] CopyArray = ArrayFromRange(Original, startIndex, length); 

następnie copyArray będzie być:

[1 | 2 | 3 | 4 | 5] nie chcę używać Array.Copy bo będzie to pętla, aby uzyskać kolejne plastry

więc chciałbym zrobić

int length = 3; 
for(int i = 0; i < OriginalArray.Length; i++) 
{ 
    int[] CopyArray = ArrayFromRange(OriginalArray, i, length); 
    // perform some operations 
} 

Dałoby mi tablicę 4 elementów za każdym razem wykonuje pętli to i wtedy zrobię kilka operacji. Ale gdybym zrobił Array.Copy, to rzuciłby OutOfBoundsException, gdy pętla i otrzyma wartość 13, spróbuje skopiować tablicę [15], która nie istnieje. Chcę uniknąć tego rodzaju błędów.

Zajmuję na WinForm, .NET 4.0

+0

przeciwieństwie na forach dyskusyjnych, nie używamy "Dziękuję" ani "Każda pomoc doceniana" lub podpisy na [tak]. Zobacz sekcję "[Powinieneś" Cześć "," dziękuję ", slogany i pozdrowienia z postów?] (Http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be -reoved-from-posts). –

Odpowiedz

8

Myślę, że najlepszym sposobem, aby traktować swoje podejście byłoby z IEnumerable obiektów, szczególnie przy użyciu LINQ. IEnumerable to interfejs oznaczający "możesz wywołać foreach na tym obiekcie". Jest zaimplementowany dla tablic, a także dla innych obiektów używanych do wysyłania zapytań o kolekcje - częścią tego jest, że nie musisz specjalnie wiedzieć, CO są te obiekty; po prostu wyliczaj każdy przedmiot, kiedy go potrzebujesz.

using System.Linq; // put this at the top of the .cs, not mid-code. 

int startIndex = 0; 
int lenght= 5; 
IEnumerable<int> CopyArray = Original.Skip(startIndex).Take(lenght); 

Napisałem to w notatniku, więc jest możliwe, że coś mi umknęło, ale to powinno dać ci to, czego potrzebujesz. Można pominąć .Skip (startIndex) udział czy to zawsze będzie 0. Aby uzyskać dostęp każdy int:

foreach (int value in CopyArray) { 
    // TODO with value?? 
} 
+1

Po prostu notka, możesz rzucić dodatkową '.ToArray()' lub '.ToList()' na końcu tego, w przeciwnym razie jej wykonanie zostanie odroczone i uruchomione za każdym razem iterowane Oznacza to, że jeśli wartości w oryginalnej tablicy ulegną zmianie, wówczas 'CopyArray' przyniesie zmienione wartości również podczas iteracji.EDYCJA: Możesz również wspomnieć, że 'Pomiń' i' Przyjmij' są wystarczająco łagodne, aby nie rzucały błędów 'IndexOutOfRangeException'. –

+0

Ach tak, absolutnie. To nie jest optymalne dla wszystkich przypadków użycia, ale brzmi to tak, jak byłoby w przypadku danego pytania. Z drugiej strony istnieją interesujące przypadki, w których warto mieć zmienną, która za każdym razem automatycznie filtruje/sortuje/etc. – Katana314

+0

@ Chris Sinclair dziękuję wam, to było to, czego potrzebowałem. Nie wiem prawie nic na temat Linq, ale po przeczytaniu dokumentacji Skip, Take i ToArray() udało mi się ją zakodować i, co ważniejsze, zrozumieć. – HardCodeStuds

0

Można nadal używać Array.Copy() ale wystarczy, aby upewnić się, że wskaźnik znajduje się w zasięgu:

T[] ArrayFromRange<T>(T[] originalArray, int startIndex, int length) 
{ 
    int actualLength = Math.Min(length, originalArray.Length - startIndex); 
    T[] copy = new T[actualLength]; 
    Array.Copy(originalArray, startIndex, copy, 0, actualLength); 
    return copy; 
} 

W przykładzie ostatnie dwie tablice w pętli będzie {14,15} i {15}.

0

Jeśli wolisz metodę, która zwraca tablicę skróconą, mogę dostarczyć jeden z nich, ale jestem przy założeniu jest to, co chcesz: (I tak, to zostało przetestowane)

using System; 
namespace ArraySlice 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      byte[] array1 = { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 }; 
      byte[] array2 = GetSlice<byte>(array1, 5, 10); 
      for (int i = 0; i < array2.Length; i++) 
      { 
       Console.WriteLine(array2[i]); 
      } 
      Console.ReadKey(); 
     } 
     static T[] GetSlice<T>(T[] array, int start, int length) 
     { 
      T[] result = new T[length]; 
      for (int i = 0; i < length; i++) 
      { 
       result[i] = ((start + i) < array.Length) ? array[start + i] : default(T); 
      } 
      return result; 
     } 
    } 
} 
Powiązane problemy