Tablice indeksowane

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Tablice indeksowane przechowują serie jednej lub więcej wartości uporządkowane ta, że do każdej z wartości można uzyskać dostęp za pomocą nieoznakowanej wartości całkowitej. Pierwszy indeks to zawsze liczba 0, a jego przyrost dla każdego kolejnego dodanego do tablicy elementu to 1. W języku ActionScript 3.0 dwie klasy są używane jako tablice indeksowane: klasa Array i klasa Vector.

W tablicach indeksowanych liczba indeksu jest nieoznakowaną 32-bitową liczbą całkowitą. Maksymalny rozmiar tablicy indeksowanej to 2 32 - 1 lub 4 294 967 295. Próba utworzenia tablicy wykraczającej poza rozmiar maksymalny skutkuje błędem wykonania.

Aby uzyskać dostęp do określonego elementu tablicy indeksowanej, należy skorzystać z operatora dostępu do tablicy ( [] ) w celu określenia indeksu elementu, do którego jest uzyskiwany dostęp. Poniższy kod reprezentuje na przykład pierwszy element (element z indeksem 0) w tablicy indeksowanej o nazwie songTitles .

songTitles[0]

Połączenie nazwy zmiennej tablicy z indeksem w nawiasach kwadratowych pełni rolę pojedynczego identyfikatora. (Innymi słowy: może być używana w dowolny sposób, w jaki można korzystać z nazwy zmiennej). Do elementu tablicy indeksowanej można przypisać wartość, korzystając z nazwy i indeksu po lewej stronie instrukcji przypisania:

songTitles[1] = "Symphony No. 5 in D minor";

I podobnie: z elementu tablicy indeksowanej można uzyskać wartość, korzystając z nazwy i indeksu po prawej stronie instrukcji przypisania:

var nextSong:String = songTitles[2];

Można również użyć zmiennej w nawiasach kwadratowych zamiast jawnego określania wartości. (Zmienna musi zawierać nieujemną liczbę całkowitą, taką jak unit, dodatnia wartość int lub dodatnia instancja Number (integer)). Ta technika jest używana najczęściej w celu wykonania pętli po elementach w tablicy indeksowanej oraz w celu wykonania operacji na niektórych lub wszystkich tych elementach. Poniższy kod demonstruje tę technikę. W kodzie zastosowano pętlę w celu uzyskania dostępu do każdej wartości w obiekcie Array o nazwie oddNumbers . Instrukcja trace() służy do wyświetlania każdej wartości w postaci „oddNumber[ indeks ] = wartość ”.

var oddNumbers:Array = [1, 3, 5, 7, 9, 11]; 
var len:uint = oddNumbers.length; 
for (var i:uint = 0; i < len; i++) 
{ 
    trace("oddNumbers[" + i.toString() + "] = " + oddNumbers[i].toString()); 
}

Klasa Array

Pierwszy typ tablicy indeksowanej to klasa Array. Instancja klasy Array może zawierać wartość danych dowolnego typu. Jeden obiekt Array może zawierać obiekty różnych typów danych. Na przykład: pojedyncza instancja klasy Array może zawierać wartość String w indeksie 0, instancję Number w indeksie 1 i obiekt XML w indeksie 2.

Klasa Vector

Innym typem tablicy indeksowanej, który jest dostępny w języku ActionScript 3.0, jest klasa Vector. Wystąpienie klasy Vector jest tablicą określonego typu , co oznacza, że wszystkie elementy w wystąpieniu klasy Vector mają zawsze ten sam typ danych.

Uwaga: Klasa Vector jest dostępna począwszy od wersji 10 programu Flash Player 10 i wersji 1.5 środowiska Adobe AIR.

Podczas deklarowania zmiennej Vector lub tworzenia instancji obiektu Vector należy jawnie określić typ danych obiektów, jakie może zawierać instancja klasy Vector. Podany w tym miejscu typ danych jest określany jako typ bazowy klasy Vector. W czasie wykonywania oraz w czasie kompilacji (w trybie dokładnym) sprawdzany jest każdy kod, który ustawia wartość elementu Vector lub pobiera wartość z elementu Vector. Jeśli typ danych obiektu dodawanego lub pobieranego nie jest zgodny z typem bazowym Vector, powstaje błąd.

Oprócz ograniczeń dotyczących typów danych klasa Vector posiada inne, które odróżniają ją od klasy Array:

  • Instancja Vector to tablica zagęszczona. Obiekt Array może zawierać wartości w indeksach 0 i 7, nawet jeśli nie zawiera wartości w pozycjach od 1 do 6. Jednak wystąpienie klasy Vector musi zawierać wartość (lub element null ) pod każdym indeksem.

  • Instancja klasy Vector może opcjonalnie mieć stałą długość. Oznacza to, że liczba elementów, jakie zawiera ta instancja Vector, nie może ulec zmianie.

  • Dostęp do elementów instancji klasy Vector jest sprawdzany pod względem ograniczeń zakresu. Niemożliwy jest odczyt wartości w pozycji indeksu większego od ostatniego elementu ( length - 1). Nie można ustawić wartości w indeksie przekraczającym bieżący ostatni indeks o jeden. (Czyli można ustawić wartość jedynie w pozycji istniejącego indeksu lub indeksu [length] ).

W wyniku tych ograniczeń wystąpienie klasy Vector charakteryzują trzy podstawowe zalety, których nie ma wystąpienie klasy Array z elementami należącymi do jednej klasy:

  • Wydajność: w porównaniu z instancją Array dostęp i iteracje elementów tablicy można uzyskać dużo szybciej w przypadku instancji Vector.

  • Bezpieczeństwo typu: w trybie dokładnym kompilator może wskazywać błędy dotyczące typu danych. Do przykładów takich błędów należą: przypisywanie wartości niepoprawnego typu danych do instancji klasy Vector lub oczekiwanie niepoprawnego typu danych podczas odczytu wartości z instancji klasy Vector. W czasie wykonywania typy danych również są sprawdzane podczas dodawania danych lub odczytywania danych z obiektu Vector. Użycie metody push() lub unshift() w celu dodania wartości do wystąpienia klasy Vector powoduje, że typy danych argumentów nie są sprawdzane w czasie kompilacji. Podczas korzystania z tych metod wartości są sprawdzane w czasie wykonywania.

  • Niezawodność: Sprawdzanie zakresów w czasie wykonywania (lub sprawdzanie stałych długości) powoduje, że niezawodność operowania na obiektach klasy Vector jest znacznie większa niż w przypadku operowania na obiektach klasy Array.

Oprócz dodatkowych ograniczeń i zalet klasa Vector bardzo przypomina klasę Array. Właściwości i metody obiektu Vector są podobne — w większości identyczne — do właściwości i metod obiektu Array. W większości przypadków, w których można zastosować klasę Array, w której wszystkie elementy należą do tego samego typu danych, preferowane jest zastosowanie instancji Vector.

Tworzenie tablic

Istnieje kilka technik tworzenia instancji klasy Array lub klasy Vector. Jednak techniki służące do tworzenia poszczególnych typów tablic są różne.

Tworzenie instancji klasy Array

Obiekt Array można utworzyć przez wywołanie konstruktora Array() lub za pomocą składni literału Array.

Funkcja konstruktora Array() może być używana na trzy sposoby. Po pierwsze, wywołanie konstruktora bez argumentów daje tablicę pustą. Użytkownik może skorzystać z właściwości length klasy Array w celu upewnienia się, że tablica nie zawiera żadnych elementów. Na przykład w poniższym kodzie wywoływany jest konstruktor Array() bez argumentów.

var names:Array = new Array(); 
trace(names.length); // output: 0

Po drugie, używanie liczby w charakterze jedynego parametru dla konstruktora Array() powoduje, że tworzona jest tablica o tej długości, a wartość każdego z jej elementów jest ustawiona na undefined . Argument musi być nieoznaczoną liczbą całkowitą z przedziału od 0 do 4 294 967 295. Na przykład w poniższym kodzie wywoływany jest konstruktor Array() z pojedynczym argumentem liczbowym.

var names:Array = new Array(3); 
trace(names.length); // output: 3 
trace(names[0]); // output: undefined 
trace(names[1]); // output: undefined 
trace(names[2]); // output: undefined

Po trzecie, wywołanie konstruktora i przekazanie listy elementów jako parametrów powoduje utworzenie tablicy z elementami odpowiadającymi poszczególnym parametrom. Poniższy kod powoduje przekazanie trzech argumentów do konstruktora Array() .

var names:Array = new Array("John", "Jane", "David"); 
trace(names.length); // output: 3 
trace(names[0]); // output: John 
trace(names[1]); // output: Jane 
trace(names[2]); // output: David

Tablice można również tworzyć za pomocą literałów Array. Literał Array może zostać przypisany bezpośrednio do zmiennej tablicy, zgodnie z przykładem poniżej:

var names:Array = ["John", "Jane", "David"];

Tworzenie instancji klasy Vector

W celu utworzenia wystąpienia klasy Vector należy wywołać konstruktor Vector.<T>() . Wystąpienie klasy Vector można również utworzyć przez wywołanie funkcji globalnej Vector.<T>() . Ta funkcja konwertuje określony obiekt na wystąpienie klasy Vector. W programie Flash Professional CS5 i nowszych wersjach, Flash Builder 4 i nowszych wersjach oraz Flex 4 i nowszych wersjach można także utworzyć instancję wektora, korzystając ze składni literału klasy Vector.

Przy każdej deklaracji zmiennej Vector (podobnie jak parametru Vector albo typu wartości zwracanej przez metodę) określany jest typ bazowy zmiennej Vector. Typ bazowy jest również określany podczas tworzenia wystąpienia klasy Vector przez wywołanie konstruktora Vector.<T>() . Oznacza to, że każdemu wpisowi Vector w języku ActionScript towarzyszy typ bazowy.

Do utworzenia typu bazowego Vector służy składnia parametru type. Parametr type występuje bezpośrednio za słowem Vector w kodzie. Składnia obejmuje znak kropki ( . ), a następnie nazwę klasy bazowej otoczoną nawiasami trójkątnymi ( <> ), tak jak w poniższym przykładzie.

var v:Vector.<String>; 
v = new Vector.<String>();

W pierwszym wierszu przykładu zmienna v została zadeklarowana jako wystąpienie klasy Vector.<String> . Reprezentuje więc tablicę indeksowaną, która może zawierać tylko wystąpienia klasy String. W drugim wierszu jest wywoływany konstruktor Vector() w celu utworzenia wystąpienia o takim samym typie Vector (czyli obiektu Vector, w którym wszystkie elementy są obiektami String). Obiekt ten jest przypisywany do zmiennej v .

Korzystanie z funkcji Vector<T>()

Jeśli konstruktor Vector.<T>() jest używany bez żadnych argumentów, oznacza to, że tworzy on puste wystąpienie klasy Vector. W celu sprawdzenia, czy wystąpienie klasy Vector jest puste, należy sprawdzić wartość jego właściwość length . Poniższy przykładowy kod wywołuje konstruktor Vector.<T>() bez argumentów.

var names:Vector.<String> = new Vector.<String>(); 
trace(names.length); // output: 0

Jeśli z góry znana jest liczba elementów wymagana w wystąpieniu klasy Vector, można wstępnie zdefiniować liczbę elementów w wystąpieniu klasy Vector. W celu utworzenia wystąpienia klasy Vector z określoną liczbą elementów należy wprowadzić liczbę elementów jako pierwszy parametr (parametr length ). Elementy wystąpienia klasy Vector nie mogą być puste, dlatego są wypełniane wystąpieniami typu bazowego. Jeśli typ bazowy jest typem odniesienia, który zezwala na wartości null , wówczas wszystkie elementy muszą zawierać wartość null . W przeciwnym wypadku wszystkie elementy będą zawierały wartość domyślną dla klasy. Na przykład zmienna uint nie może mieć wartości null . Z tego powodu w poniższym kodzie tworzone jest wystąpienie klasy Vector o nazwie ages z siedmioma elementami, a każdy z nich zawiera wartość 0.

var ages:Vector.<uint> = new Vector.<uint>(7); 
trace(ages); // output: 0,0,0,0,0,0,0 

Za pomocą konstruktora Vector.<T>() można również utworzyć obiekt Vector o stałej długości, wprowadzając wartość true dla drugiego parametru (parametru fixed ). W takim przypadku instancja klasy Vector jest tworzona z określoną liczbą elementów, a liczby elementów nie można zmienić. Należy jednak pamiętać, że w instancji klasy Vector o stałej długości można zmieniać wartości elementów.

Korzystanie z konstruktora klasy Vector przy użyciu składni literału

W programie Flash Professional CS5 i nowszych wersjach, Flash Builder 4 i nowszych wersjach oraz Flex 4 i nowszych wersjach można przekazać listę wartości do konstruktora Vector.<T>() nie można przekazać listy wartości w celu określenia wartości początkowych wystąpienia klasy Vector.

// var v:Vector.<T> = new <T>[E0, ..., En-1 ,]; 
// For example: 
var v:Vector.<int> = new <int>[0,1,2,];

Do tej składni odnoszą się następujące informacje:

  • Końcowy przecinek jest opcjonalny.

  • Puste elementy w tablicy nie są dozwolone; taka instrukcja, jak var v:Vector.<int> = new <int>[0,,2,] powoduje zgłoszenie błędu przez kompilator.

  • Nie można określić domyślnej długości instancji klasy Vector. Długość jest określana na podstawie liczby elementów na liście inicjującej instancję.

  • Nie można określić, czy instancja klasy Vector ma mieć stałą długość, czy nie. Należy zamiast tego skorzystać z właściwości fixed .

  • Jeśli elementy przekazane jako wartości nie będą zgodne z określonym typem, może dojść do utraty danych lub wystąpienia błędów. Na przykład:
    var v:Vector.<int> = new <int>[4.2]; // compiler error when running in strict mode 
    trace(v[0]); //returns 4 when not running in strict mode

Korzystanie z funkcji globalnej Vector.<T>()

Oprócz konstruktora Vector.<T>() i składni literału klasy Vector można również użyć funkcji globalnej Vector.<T>() w celu utworzenia obiektu Vector. Funkcja globalna Vector.<T>() jest funkcją konwersji. Po wywołaniu funkcji globalnej Vector.<T>() należy określić typ bazowy wystąpienia klasy Vector, jaki będzie zwracany przez metodę. Jako argument należy wprowadzić pojedynczą tablicę indeksowaną (instancję klasy Array lub Vector). Następnie metoda zwróci instancję klasy Vector z określonym typem bazowym zawierającym wartości w argumencie tablicy źródłowej. Poniższy kod prezentuje składnię wywołania funkcji globalnej Vector.<T>() .

var friends:Vector.<String> = Vector.<String>(["Bob", "Larry", "Sarah"]);

Funkcja globalna Vector.<T>() wykonuje konwersje typów danych na dwóch poziomach. Najpierw: gdy instancja klasy Array zostanie przekazana do funkcji, wówczas następuje zwrócenie instancji klasy Vector. Następnie: niezależnie od tego, czy tablica źródłowa jest instancją klasy Array czy Vector, funkcja podejmuje próbę konwersji elementów tablicy źródłowej na wartości typu bazowego. Podczas konwersji wykorzystywane są standardowe reguły konwersji typu danych z języka ActionScript. Na przykład: poniższy kod konwertuje wartości String ze źródłowej instancji klasy Array na wartości całkowite w wynikowej instancji klasy Vector. Część dziesiętna pierwszej wartości ( "1.5" ) jest obcinana, a nieliczbowa trzecia wartość ( "Waffles" ) jest przekształcana na 0 w wyniku.

var numbers:Vector.<int> = Vector.<int>(["1.5", "17", "Waffles"]); 
trace(numbers); // output: 1,17,0

Jeśli nie jest możliwa konwersja któregokolwiek z elementów źródłowych, występuje błąd.

Gdy kod wywoła funkcję globalną Vector.<T>() , a element w tablicy źródłowej jest wystąpieniem podklasy o określonym typie bazowym, wówczas element jest dodawany do wynikowego wystąpienia klasy Vector (nie występuje błąd). Użycie funkcji globalnej Vector.<T>() jest jedynym sposobem na konwersję wystąpienia klasy Vector o typie bazowym T na wystąpienie klasy Vector o typie bazowym będącym klasą nadrzędną klasy T .

Wstawianie elementów tablicy

Najprostszym sposobem dodania elementu do tablicy indeksowanej jest użycie operatora dostępu do tablicy ( [] ). Aby ustawić wartość elementu tablicy indeksowanej, należy użyć nazwy obiektu Array lub Vector oraz numeru indeksu po lewej stronie instrukcji przypisania:

songTitles[5] = "Happy Birthday";

Jeśli obiekt Array lub Vector nie zawiera jeszcze elementu w pozycji tego indeksu, indeks zostanie utworzony, a wartość zostanie w nim zapisana. Jeśli w pozycji tego indeksu istnieje wartość, nowa wartość zastąpi istniejącą.

Obiekt Array umożliwia utworzenie elementu w pozycji dowolnego indeksu. Jednak w przypadku obiektu Vector można tylko przypisać wartość do istniejącego indeksu lub do następnego dostępnego indeksu. Następny dostępny indeks odpowiada właściwości length obiektu Vector. Najbezpieczniejszym sposobem dodania nowego elementu do obiektu Vector jest użycie następującego fragmentu kodu:

myVector[myVector.length] = valueToAdd;

Trzy z metod klas Array i Vector — push() , unshift() i splice() — umożliwiają wstawianie elementów do tablicy indeksowanej. Metoda push() powoduje dołączenie co najmniej jednego elementu na końcu tablicy. Ostatni element wstawiony do tablicy za pomocą metody push() otrzymuje najwyższy numer indeksu. Metoda unshift() powoduje wstawienie co najmniej jednego elementu na początku tablicy — pod indeksem 0. Metoda splice() powoduje wstawienie dowolnej liczby pozycji pod określonym indeksem tablicy.

Poniższy przykład zawiera wszystkie trzy metody. Tworzona jest dowolna tablica o nazwie planets . Ma ona przechowywać nazwy planet w kolejności określonej ich odległością od Słońca. Przede wszystkim wywoływana jest więc metoda push() w celu dodania do tablicy pierwszego elementu: Mars . Następnie wywoływana jest metoda unshift() wstawiająca element przypadający na sam początek tablicy: Mercury . Na koniec wywoływana jest metoda splice() wstawiająca kolejno elementy Venus i Earth za pozycją Mercury , lecz przed pozycją Mars . Pierwszy argument wysłany do metody splice() , liczba całkowita 1, powoduje rozpoczęcie wstawiania od indeksu 1. Drugi argument wysyłany do metody splice() , liczba całkowita 0, wskazuje, że żadna z pozycji nie może zostać usunięta. Trzeci i czwarty argument wysyłane do metody splice() , Venus i Earth , to elementy, które mają zostać wstawione.

var planets:Array = new Array(); 
planets.push("Mars"); // array contents: Mars 
planets.unshift("Mercury"); // array contents: Mercury,Mars 
planets.splice(1, 0, "Venus", "Earth"); 
trace(planets); // array contents: Mercury,Venus,Earth,Mars

Metody push() i unshift() zwracają nieoznaczoną liczbę całkowitą reprezentującą długość zmodyfikowanej tablicy. Metoda splice() , użyta do wstawienia elementów, zwraca pustą tablicę co może wydawać się dziwne, jest jednak logiczne w kontekście uniwersalności działania metody splice() . Metody splice() można użyć nie tylko do wstawienia elementów do tablicy, lecz również do usunięcia z niej elementów. W przypadku korzystania z metody splice() do usuwania elementów zwraca ona tablicę zawierającą te usunięte elementy.

Uwaga: Jeśli właściwość fixed obiektu Vector ma wartość true , wówczas liczba elementów w obiekcie Vector nie może ulec zmianie. W przypadku próby dodania nowego elementu do obiektu Vector o stałej długości za pomocą technik opisanych w tej sekcji dochodzi do powstania błędu.

Pobieranie wartości i usuwanie elementów tablic

Najprostszym sposobem na pobranie wartości elementu z tablicy indeksowanej jest użycie operatora dostępu do tablicy ( [] ). Aby pobrać wartość elementu tablicy indeksowanej, należy użyć nazwy obiektu Array lub Vector oraz numeru indeksu po prawej stronie instrukcji przypisania:

var myFavoriteSong:String = songTitles[3];

Możliwa jest próba pobrania wartości z obiektu Array lub Vector przy użyciu indeksu, który nie zawiera żadnego elementu. W takim przypadku obiekt Array zwróci wartość undefined, a obiekt Vector zgłosi wyjątek RangeError.

Trzy metody klas Array i Vector — pop() , shift() i splice() — umożliwiają usuwanie elementów. Metoda pop() umożliwia usunięcie elementu z końca tablicy. Innymi słowy, usuwa ona element o najwyższym indeksie. Metoda shift() usuwa element z początku tablicy, co oznacza, że zawsze usuwa element o indeksie równym 0. Metoda splice() , która może być również używana do wstawiana elementów, usuwa podaną liczbę elementów, rozpoczynając od indeksu o numerze podanym w pierwszym argumencie wysłanym do metody.

W poniższym przykładzie użyto wszystkich trzech metod w celu usunięcia elementów z wystąpienia klasy Array. Utworzona została tablica o nazwie oceans , która ma zawierać nazwy dużych zbiorników wodnych. Niektóre z nazw w tablicy to raczej jeziora niż oceany, dlatego potrzebne jest ich usunięcie.

Najpierw metoda splice() jest używana do usunięcia pozycji Aral i Superior oraz wstawiania pozycji Atlantic i Indian . Pierwszy argument wysyłany do metody splice() , liczba całkowita 2, wskazuje, że operacja powinna zostać rozpoczęta od trzeciej pozycji na liście — indeksu o numerze 2. Drugi argument — 2 — oznacza, że należy usunąć dwa elementy. Pozostałe argumenty, Atlantic i Indian , są wartościami, które należy wstawić pod indeksem 2.

Następnie metoda pop() usuwa ostatni element tablicy, Huron . W kolejnym kroku metoda shift() usuwa pierwszy element tablicy, Victoria .

var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian", "Huron"]; 
oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior 
oceans.pop(); // removes Huron 
oceans.shift(); // removes Victoria 
trace(oceans);// output: Pacific,Arctic,Atlantic,Indian

Metody pop() i shift() zwracają usunięte elementy. W przypadku instancji klasy typ danych wartości zwracanej to Object, ponieważ tablice mogą zawierać dane dowolnego typu. W przypadku instancji klasy Vector typ danych wartości zwracanej jest typem bazowym klasy Vector. Metoda splice() zwraca obiekt Array lub Vector zawierający usunięte wartości. Przykład oparty na tablicy oceans można zmienić w taki sposób, aby wywołanie metody splice() powodowało przypisanie zwróconej tablicy do nowej zmiennej tablicy, zgodnie z poniższym przykładem.

var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic"); 
trace(lakes); // output: Aral,Superior

Użytkownik może również spotkać się z kodem, który korzysta z operatora delete dla elementu obiektu Array. Operator delete ustawia dla elementu obiektu Array wartość undefined , lecz nie usuwa elementu z tablicy. Na przykład poniższy kod korzysta z operatora delete dla trzeciego elementu w tablicy oceans , lecz długość tablicy pozostaje równa 5.

var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"]; 
delete oceans[2]; 
trace(oceans);// output: Arctic,Pacific,,Indian,Atlantic 
trace(oceans[2]); // output: undefined 
trace(oceans.length); // output: 5

Obiekt Array lub Vector można skrócić za pomocą właściwości length . Po ustawieniu właściwości length tablicy indeksowanej na wartość mniejszą od aktualnej długości tablicy jest ona skracana, co powoduje usunięcie elementów zapisanych pod numerem indeksu wyższym niż nowa wartość właściwości length pomniejszona o 1. Jeśli na przykład tablica oceans została posortowana tak, że wszystkie poprawne elementy znajdują się w jej górnej części, można za pomocą właściwości length usunąć elementy z końca tablicy, zgodnie z poniższym kodem.

var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"]; 
oceans.length = 2; 
trace(oceans); // output: Arctic,Pacific
Uwaga: Jeśli właściwość fixed obiektu Vector ma wartość true , wówczas liczba elementów w obiekcie Vector nie może ulec zmianie. W przypadku próby usunięcia elementu lub skrócenia obiektu Vector o stałej długości za pomocą technik opisanych w tej sekcji dochodzi do powstania błędu.

Sortowanie tablicy

Dostępne są trzy metody — reverse() , sort() oraz sortOn() — umożliwiające zmienianie kolejności elementów tablicy indeksowanej przez sortowanie albo odwracanie kolejności. Wszystkie te metody modyfikują istniejącą tablicę. W poniższej tabeli przedstawiono podsumowanie tych metod oraz ich zachowanie dla obiektów Array i Vector:

Metoda

Zachowanie obiektu Array

Zachowanie obiektu Vector

reverse()

Zmienia kolejność elementów w taki sposób, że ostatni element staje się pierwszym elementem, a element przedostatni staje się drugim itd.

Takie same, jak zachowanie obiektu Array

sort()

Umożliwia sortowanie elementów obiektu Array na różne (predefiniowane) sposoby, np. w porządku alfabetycznym i liczbowym. Można również określić niestandardowy algorytm sortowania.

Sortuje elementy zgodnie ze zdefiniowanym niestandardowym algorytmem sortowania

sortOn()

Umożliwia sortowanie obiektów, które zawierają jedną lub większą liczbę wspólnych właściwości — poprzez określenie jednej lub większej liczby właściwości, jakie zostaną wykorzystane jako klucze sortowania

Niedostępne w klasie Vector

Metoda reverse()

Metoda reverse() nie korzysta z żadnych parametrów i nie zwraca wartości; pozwala ona jednak odwracać kolejność w tablicy przez przełączanie między porządkiem aktualnym a „odwróconym”. Poniższy przykład ilustruje odwracanie kolejności listy oceanów w tablicy oceans .

var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"]; 
oceans.reverse(); 
trace(oceans); // output: Pacific,Indian,Atlantic,Arctic

Proste sortowanie za pomocą metody sort() (tylko klasa Array)

W przypadku wystąpienia klasy Array metoda sort() zmienia kolejność elementów, stosując domyślny porządek sortowania . Domyślny porządek sortowania ma następującą charakterystykę:

  • W sortowaniu jest rozróżniana wielkość znaków, co oznacza, że wielkie litery poprzedzają małe litery. Na przykład, litera D poprzedza literę b.

  • Sortowanie odbywa się rosnąco, co oznacza, że znaki o niższych kodach (jak A) poprzedzają znaki o wyższych kodach (jak B).

  • Sortowanie powoduje umieszczenie wartości identycznych w sąsiedztwie, lecz w losowej kolejności.

  • Sortowanie jest oparte na ciągach, co oznacza, że elementy są przed porównaniem konwertowane na ciągi. (Na przykład 10 poprzedza 3, ponieważ ciąg "1" ma niższy kod niż "3" ).

Może okazać się, że konieczne jest posortowanie tablicy bez względu na wielkość liter lub w porządku malejącym. Może się również zdarzyć, że tablica będzie zawierała liczby, które będzie trzeba posortować w porządku liczbowym, nie zaś alfabetycznym. Metoda sort() klasy Array zawiera parametr options , umożliwiający zmianę poszczególnych opcji sortowania domyślnego. Opcje są definiowane zestawem stałych statycznych w klasie Array, zgodnie z poniższą listą:

  • Array.CASEINSENSITIVE : Ta opcja powoduje nieroróżnianie wielkości liter przy sortowaniu. Na przykład mała litera b poprzedza wówczas wielką literę D.

  • Array.DESCENDING: Ta opcja powoduje odwrócenie domyślnego, rosnącego porządku sortowania. Na przykład litera B poprzedza literę A.

  • Array.UNIQUESORT: Ta opcja powoduje przerwanie sortowania w przypadku znalezienia dwóch identycznych wartości.

  • Array.NUMERIC: Ta opcja powoduje sortowanie liczbowe (takie, w którym 3 poprzedza 10).

W poniższym przykładzie podkreślono niektóre z tych opcji. Tworzona jest tablica o nazwie poets , która jest następnie sortowana za pomocą kilku różnych opcji.

var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; 
poets.sort(); // default sort 
trace(poets); // output: Angelou,Blake,Dante,cummings 
 
poets.sort(Array.CASEINSENSITIVE); 
trace(poets); // output: Angelou,Blake,cummings,Dante 
 
poets.sort(Array.DESCENDING); 
trace(poets); // output: cummings,Dante,Blake,Angelou 
 
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options 
trace(poets); // output: Dante,cummings,Blake,Angelou

Niestandardowe sortowanie za pomocą metody sort() (klasy Array i Vector)

Oprócz sortowania podstawowego, jakie jest dostępne dla obiektu Array, można również zdefiniować niestandardową regułę sortowania. Ta technika jest jedyną formą metody sort() , jaka jest dostępna dla klasy Vector. Aby zdefiniować własne sortowanie, należy napisać własną funkcję sortowania i przekazać ją jako argument do metody sort() .

Załóżmy na przykład, że istnieje lista nazwisk, na której każdy element zawiera imię i nazwisko osoby, lecz lista powinna zostać posortowana według nazwisk. Należy użyć własnej funkcji w celu dokonania analizy każdego elementu i użycia do sortowania tylko części stanowiącej nazwisko. Poniższy kod ilustruje, jak można to zrobić za pomocą własnej funkcji użytej w charakterze parametru dla metody Array.sort() .

var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones"); 
function orderLastName(a, b):int 
{ 
    var lastName:RegExp = /\b\S+$/; 
    var name1 = a.match(lastName); 
    var name2 = b.match(lastName); 
    if (name1 < name2) 
    { 
        return -1; 
    } 
    else if (name1 > name2) 
    { 
        return 1; 
    } 
    else 
    { 
        return 0; 
    } 
} 
trace(names); // output: John Q. Smith,Jane Doe,Mike Jones 
names.sort(orderLastName); 
trace(names); // output: Jane Doe,Mike Jones,John Q. Smith

Własna funkcja sortująca orderLastName() korzysta z wyrażenia regularnego w celu wydzielenia nazwiska z każdego z elementów, co umożliwia ich porównanie w operacji porównania. Identyfikator funkcji orderLastName służy jako jedyny parametr wywołania metody sort() dla tablicy names . Funkcja sortowania przyjmuje dwa parametry — a oraz b — ponieważ działa ona na dwóch elementach tablicy jednocześnie. Zwracana wartość funkcji sortowania wskazuje, jak powinny być posortowane elementy.

  • Zwracana wartość wynosząca -1 wskazuje, że pierwszy z parametrów, a , poprzedza drugi z parametrów, b .

  • Zwracana wartość wynosząca 1 wskazuje, że drugi parametr, b , poprzedza pierwszy parametr, a .

  • Zwracana wartość wynosząca 0 wskazuje, że elementy mają jednakowe pierwszeństwo przy sortowaniu.

Metoda sortOn() (tylko klasa Array)

Metoda sortOn() jest przeznaczona dla obiektów Array zawierających elementy, które zawierają obiekty. Obiekty te powinny mieć co najmniej jedną wspólną właściwość, która może służyć jako klucz sortowania. Metoda sortOn() zastosowana dla tablic jakiegokolwiek innego typu zwraca wyniki inne niż oczekiwane.

Uwaga: Klasa Vector nie zawiera metody sortOn() . Ta metoda jest dostępna tylko dla obiektów Array.

Poniższy przykład ilustruje modyfikację obiektu Array poets mającą na celu doprowadzenie do tego, by każdy jej element był obiektem, nie zaś ciągiem znaków. Każdy obiekt zawiera zarówno nazwisko poety, jak i rok jego urodzenia.

var poets:Array = new Array(); 
poets.push({name:"Angelou", born:"1928"}); 
poets.push({name:"Blake", born:"1757"}); 
poets.push({name:"cummings", born:"1894"}); 
poets.push({name:"Dante", born:"1265"}); 
poets.push({name:"Wang", born:"701"});

Za pomocą metody sortOn() można posortować obiekt Array według właściwości born . Metoda sortOn() definiuje dwa parametry: fieldName i options . Argument fieldName musi zostać określony jako ciąg. W poniższym przykładzie metoda sortOn() jest wywoływana z dwoma argumentami: "born" oraz Array.NUMERIC . Argument Array.NUMERIC jest używany w celu zapewnienia, że sortowanie zostało wykonane liczbowo, nie zaś alfabetycznie. Jest to dobra praktyka, nawet, jeśli wszystkie liczby mają taką samą liczbę cyfr, ponieważ zapewnia kontynuowanie sortowania zgodnie z oczekiwaniami, nawet już po późniejszym dodaniu większej lub mniejszej liczby cyfr do tablicy.

poets.sortOn("born", Array.NUMERIC); 
for (var i:int = 0; i < poets.length; ++i) 
{ 
    trace(poets[i].name, poets[i].born); 
} 
/* output: 
Wang 701 
Dante 1265 
Blake 1757 
cummings 1894 
Angelou 1928 
*/

Sortowanie bez modyfikowania tablicy oryginalnej (tylko klasa Array)

Zwykle metody sort() i sortOn() modyfikują obiekt Array. Aby posortować obiekt Array bez modyfikowania istniejącej tablicy, należy przekazać stałą Array.RETURNINDEXEDARRAY jako część parametru options . Opcja ta żąda, by metody zwracały nowy obiekt Array, który odzwierciedla sortowanie, a pozostawiały oryginalny obiekt Array niezmieniony. Obiekt Array zwrócony za pomocą jednej z metod jest prostym obiektem Array zawierającym numery indeksów, które odpowiadają nowemu porządkowi sortowania, i nie zawiera żadnych elementów z oryginalnego obiektu Array. Aby na przykład możliwe było posortowanie obiektu poets klasy Array według roku urodzenia bez modyfikowania tablicy, należy włączyć stałą Array.RETURNINDEXEDARRAY jako część argumentu przekazanego dla parametru options .

W poniższym przykładzie zwracane informacje o indeksach zapisywane są w obiekcie Array o nazwie indices . Następnie tablica indices w połączeniu z niezmienioną tablicą poets jest używana do wygenerowania wyników w kolejności roku urodzenia.

var indices:Array; 
indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY); 
for (var i:int = 0; i < indices.length; ++i) 
{ 
    var index:int = indices[i]; 
    trace(poets[index].name, poets[index].born); 
} 
/* output: 
Wang 701 
Dante 1265 
Blake 1757 
cummings 1894 
Angelou 1928 
*/

Zapytania dotyczące tablic

Cztery metody klas Array i Vector — concat() , join() , slice() i toString() — wyszukują w tablicy informacje, ale nie modyfikują tablicy. Metody concat() i slice() zwracają nowe tablice. Metody join() i toString() zwracają ciągi. Metoda concat() pobiera nową tablicę lub listę elementów w postaci argumentów i łączy ją z istniejącą tablicą w celu utworzenia nowej tablicy. Metoda slice() ma dwa parametry o nazwach startIndex oraz endIndex . Zwraca nową tablicę zawierającą kopie elementów powycinanych z istniejącej tablicy. Warstwa ta zaczyna się od elementu startIndex , a kończy elementem poprzedzającym endIndex . Należy pamiętać, że element na pozycji endIndex nie jest uwzględniany w wartości zwracanej.

Poniższy przykład ilustruje używanie metod concat() oraz slice() do tworzenia nowych tablic przy użyciu elementów innych tablic.

var array1:Array = ["alpha", "beta"]; 
var array2:Array = array1.concat("gamma", "delta"); 
trace(array2); // output: alpha,beta,gamma,delta 
 
var array3:Array = array1.concat(array2); 
trace(array3); // output: alpha,beta,alpha,beta,gamma,delta 
 
var array4:Array = array3.slice(2,5); 
trace(array4); // output: alpha,beta,gamma

Korzystając z metod join() oraz toString() , można zwracać zawartość tablic w postaci ciągów. Jeśli dla metody join() nie są używane żadne parametry, te dwie metody zachowują się identycznie, zwracając ciąg zawierający listę rozdzielaną przecinkami, składającą się ze wszystkich elementów w tablicy. Metoda join() w przeciwieństwie do metody toString() przyjmuje parametr o nazwie delimiter , pozwalający wybrać symbol, który będzie rozdzielał poszczególne elementy w zwracanym ciągu.

W poniższym przykładzie tworzony jest obiekt Array o nazwie rivers oraz wywoływane są metody join() i toString() zwracające wartości z obiektu Array w postaci ciągu. Metoda toString() służy do zwracania wartości rozdzielanych przecinkami ( riverCSV ), podczas gdy metoda join() służy do zwracania wartości rozdzielanych znakiem + .

var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"]; 
var riverCSV:String = rivers.toString(); 
trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi 
var riverPSV:String = rivers.join("+"); 
trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi

Jedną z kwestii, jakie należy mieć na uwadze w przypadku posługiwania się metodą join() , jest to, że wszelkie zagnieżdżone wystąpienia klas Array lub Vector są zawsze zwracane w postaci rozdzielanej przecinkami, niezależnie od tego, jaki separator wybrano dla elementów tablicy głównej. Ilustruje to poniższy przykład.

var nested:Array = ["b","c","d"]; 
var letters:Array = ["a",nested,"e"];  
var joined:String = letters.join("+"); 
trace(joined); // output: a+b,c,d+e