Warning: include() [function.include]: open_basedir restriction in effect. File(/usr/local/php5.2/lib/php/_ogg.php) is not within the allowed path(s): (/home/doman/:/tmp:/usr/local/lib/php/:/usr/sbin/:/usr/bin/:/usr/local/bin/:/usr/local/sbin/:/bin/:/sbin/) in /home/doman/domains/kursjs.pl/public_html/inc/_header.php on line 11

Tablice

Wyobraź sobie, że musisz przechować 10 wartości. Tworzysz więc 10 zmiennych. I wszystko jest ok do czasu, gdy musisz na każdej z nich wykonać określoną czynność (na przykład pomnożyć przez 2). Zaczynają się schody. A schody te zwiększają się gdy dochodzisz do momentu kiedy nie możesz z góry określić ile ma być tych zmiennych, lub gdy tych zmiennych robi się nie 10, a np 200 razy tyle. Z tablicami takich problemów nie ma.
Poza tym tablice oferują dodatkowe metody, które robią z nich bardzo dobre narzędzie pracy. O czym przekonasz się już za momencik ;)

Tworzenie nowej tablicy

Nic trudnego. Wystarczy skorzystać z poniższej instrukcji:


//deklaracja za pomocą literału
var ourTable = ['Marcin', 'Ania', 'Agnieszka'];

Tak samo jak w przypadku tekstów i liczb do deklaracji tablicy możemy skorzystać z konstruktora:


var ourTable = new Array('Marcin', 'Ania', 'Agnieszka');

Deklaracja za pomocą konstruktora jest nieznacznie wolniejsza od deklaracji za pomocą literału, ale pozwala tworzyć puste tablice o zadanej długości:


var ourTable = new Array(6); //tworzy pustą tablicę o długości 6

Używanie konstruktora nie jest zalecane, bo zapis jest mniej czytelny, a i może on powodować błędy.

Teraz aby uzyskać dostęp do 2 elementu tablicy skorzystamy z instrukcji:


console.log( ourTable[1] ); //wypisze się Ania

Zwróć uwagę, że tablice są indeksowane od 0, tak więc pierwszy element tablicy ma index - 0, drugi - 1, trzeci - 2 itd.

Aby dodać nową wartość do tablicy po prostu ustawiamy nową wartość w odpowiednim indeksie tablicy lub korzystamy z metody push()::


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
ourTable[3] = "Piotrek";
ourTable[4] = "Grzegorz";

console.log(ourTable[3] + ' i ' + ourTable[4]); //wypisze się "Piotrek i Grzegorz"

ourTable.push('Michał');
console.log(ourTable[5]); //wypisze Michał

Właściwość length

Każda tablica udostępnia nam właściwość length dzięki której możemy określić długość tej tablicy (ilość elementów). Dzięki temu możemy poznać index ostatniego elementu oraz w łatwy sposób przeprowadzać pętlę po wszystkich elementach naszej tablicy.


var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Piotrek', 'Grześ', 'Magda'];

console.log(ourTable.length); //6

Aby odwołać się do ostatniego elementu musimy odjąć 1 od liczby elementów (bo indexowanie jest od 0):


console.log( ourTable[ourTable.length-1] );

Pętla po tablicy

Możemy także wykonywać pętle po tablicy - chociażby by móc wypisać wszystkie elementy tablicy, sprawdzić je lub dla każdego z nich wykonać jakąś operację.
Aby zrobić pętlę po tablicy skorzystamy z jednej z dwóch pętli:


var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Piotrek', 'Grześ', 'Magda'];

for (var i=0; i<ourTable.length; i++) {
    console.log('Imię numer ' +i+ ': ' +ourTable[i]);
}

//lub lepiej
ourTable.forEach(function(el, i) {
    console.log('Imię numer ' +i+ ': ' +el);
});

Tablice wielowymiarowe

Możemy też tworzyć tablice wielowymiarowe - czyli tablice w tablicach. Do czego może się to przydać?
Powiedzmy że chcemy manipulować na rekordach dotyczących osób. Możemy wtedy stworzyć tablicę, w której w każdym indeksie będzie rekord w formie tablicy zawierająca dane osoby:


var ourTable = [];
ourTable[0] = ['Marcin' , '183'];
ourTable[1] = ['Ania' , '173'];
ourTable[2] = ['Agnieszka' , '170'];
//...itp

console.log('imię: ' + ourTable[0][0] + ', wzrost: ' + ourTable[0][1]);
console.log('imię: ' + ourTable[1][0] + ', wzrost: ' + ourTable[1][1]);
console.log('imię: ' + ourTable[2][0] + ', wzrost: ' + ourTable[2][1]);

Łączenie elementów tablicy przy pomocy metody join()

Metoda join() służy do łączenia kolejnych elementów w jeden tekst. Opcjonalnym parametrem tej metody jest znak, który będzie oddzielał kolejne elementy w utworzonym tekście. Jeżeli go nie podamy będzie użyty domyślny znak przecinka:


var ourTable = ["Marcin", "Ania", "Agnieszka"];
console.log(ourTable.join()); //wypisze się "Marcin,Ania,Agnieszka"
console.log(ourTable.join(" - ")); //wypisze się "Marcin - Ania - Agnieszka"
console.log(ourTable.join(" + ")); //wypisze się "Marcin + Ania + Agnieszka"

Odwracanie kolejności elementów tablicy przy pomocy metody reverse()

Dzięki metodzie reverse() możemy odwrócić elementy naszej tablicy:


var ourTable = ["numer 1" , "numer 2" , "numer 3" , "numer 4"];

console.log('Przed: ' + ourTable);
ourTable.reverse()
console.log('Po: ' + ourTable);

Sortowanie tablic za pomocą metody sort()

Metoda sort() służy do sortowania tablic metodą "bombelkową". Powiedzmy, że mamy tablicę z niepoukładanymi wartościami, i chcemy ją posortować:


var ourTable = ['Marcin', 'Ania', 'Piotrek', 'Grześ'];
ourTable.sort()
console.log( ourTable ); //wypisze się "Ania, Grześ, Marcin, Piotrek"

Standardowo Javascript segreguje tablice leksykalnie (czyli tak jak w książce telefonicznej). Powoduje to w niektórych przypadkach nieoczekiwane rezultaty - na przykład 1200 będzie mniejsze od 300 (bo liczy się pierwsza cyfra) itp.
Aby móc posegregować naszą tablicę według własnych kryteriów, musimy skorzystać z dodatkowego parametru, który metoda sort() może opcjonalnie przyjmować. Parametr ten jest nazwą naszej funkcji sortującej. Pisząc taką funkcję musimy pamiętać o 3 sprawach:

  • Jeżeli funkcja(a, b) zwróci wartość mniejszą od 0, to wartość a będzie miała mniejszy index od b
  • Jeżeli funkcja(a, b) zwróci 0, to indexy wartości a i b pozostaną bez zmian
  • Jeżeli funkcja(a, b) zwróci wartość większą od 0, to wartość a będzie miała większy index od b

Tak więc ogólna postać funkcji sortującej wygląda tak:


function porownaj(A, B) {
    if (A jest mniejsze od B) {return -1}
    if (A jest większe od B) {return 1}   
    //jeżeli A równa się B
    return 0
}

Przykładowo aby posegregować wartości liczbowe musimy utworzyć funkcję:


//tworzymy funkcję do segregacji liczb
function compareNumbers(a, b) {
    return a - b
}

var ourTable = [100, 10, 25, 310, 1200, 400];

console.log('Bez sortowania: ' + ourTable );

ourTable.sort()
console.log( 'ourTable.sort(): ' + ourTable );

ourTable.sort(compareNumbers)
console.log('ourTable.sort(compareNumbers): ' + ourTable);

Oczywiście możemy sami wymyślać nasze własne kryteria segregacji (na przykład by cyfry były "mniejsze" od liter, lub też duże litery były "mniejsze" od małych liter...).

Łączenie dwóch tablic

Do połączenia dwóch tablic wykorzystamy metodę concat(array1, ...), która jako parametr przyjmuje jedną lub kilka tablic:


    var animals = ["Pies", "Kot"];
    var animals2 = ["Słoń", "Wieloryb"];
    var animals3 = ["Chomik ninja", "Świnka morderca"];

    var newTableSmall = animals.concat(animals2);
    var newTableBig = animals.concat(animals2, animals3);

    console.log(newTableSmall); //wypisze ["Pies", "Kot", "Słoń", "Wieloryb"]
    console.log(newTableBig); //wypisze ["Pies", "Kot", "Słoń", "Wieloryb", "Chomik ninja", "Świnka morderca"]

Mieszanie tablicy

Skoro potrafimy posortować tablicę, to nauczmy się też wykonać operację wręcz odwrotną - pomieszać przypadkowo elementy tablicy. Javascript niestety nie udostępnia metody do "psucia" tablicy, więc będziemy musieli napisać ją sobie sami:


function mixArray(arr) {
    for (var i=0; i<arr.length; i++) { //wykonujemy pętlę po całej tablicy
        var j = Math.floor(Math.random() * arr.length); //losujemy wartość z przedziału 0 - tablica.length-1
        var temp = arr[i]; //pod zmienną temp podstawiamy wartość bieżącego indexu
        arr[i] = arr[j]; //pod bieżący index podstawiamy wartość z indexu wylosowanego
        arr[j] = temp; //pod wylosowany podstawiamy wartość z bieżącego indexu
    }
    return arr;
}

W parametrze tej funkcji podajemy tablicę, która ma być pomieszana. Zasada działania tej funkcji jest podobna do zasady działania segregowania bąbelkowego (ta sama metoda zamiany indeksów).

Wyliczanie średniej wartości elementów tablicy

Znowu musimy polegać tylko na własnym talencie programistycznym ;). Zasada bardzo prosta - dodaj wszystkie elementy tablicy i podziel je przez ilość tych elementów:


function tableAverage(arr) {
    var sum = 0;
    for (var i=0; i<arr.length; i++) {
        sum += arr[i];
    }
    return (sum / i);
}

Największa i najmniejsza wartość w tablicy

Jak sprawdzić która wartość w tablicy jest największa? Podstawiamy pod zmienną max pierwszy element tablicy. Wykonujemy pętlę po pozostałych elementach tablicy. Jeżeli dany element jest większy od zmiennej max, to pod tą zmienną podstawiamy wartość tego elementu. I tak do końca tablicy... Tak samo czynimy w przypadku znajdowania najmniejszej wartości. Różnica polega na sprawdzaniu, czy wartość sprawdzanego elementu jest mniejsza od zmiennej mins


function tableMax(arr) {
    var max = arr[0];
    for (var i=1; i<arr.length; i++) {
        max = (arr[i] > max)? arr[i] : max;
    }
    return max;
}

function tableMin(arr) {
    var min = arr[0];
    for (var i=1; i<arr.length; i++) {
        min = (arr[i] < min)? arr[i] : min;
    }
    return min;
}

Powyższe przepisy są bardzo proste, co nie znaczy że najbardziej optymalne. Inne ciekawe podejścia do wyszukiwania najmniejszej i największej wartości w tablicy znajdziesz na stronie: http://stackoverflow.com/questions/1669190/javascript-min-max-array-values

Użycie metody slice()

Metoda slice(od, do) zwraca nową tablicę zawierającą wycięte elementy z tablicy na której została wywołana. Metoda ta nie modyfikuje tablicy, na której jest wywoływana.
Pierwszy parametr od wskazuje na index, od którego ma "wyciąć" elementy, a do analogicznie wskazuje indeks do kąd będziemy ciąć. Metoda ta nie modyfikuje tablicy na której została wywołana, a tylko zwraca elementy które zostały wycięte:


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];

var ourTable2 = ourTable.slice(0, 1)
console.log(ourTable2); //wypisze się "Marcin"
console.log(ourTable); //wypisze się "Marcin, Ania, Agnieszka"


var ourTable3 = ourTable.slice(0,2)
console.log(ourTable3); //wypisze się "Marcin, Ania"

var ourTable4 = ourTable.slice(0,5)
console.log(ourTable4); //wypisze się "Marcin, Ania, Agnieszka"

var ourTable5 = ourTable.slice(0,1)
console.log(ourTable5); //wypisze się "Marcin"

Usuwanie lub dodawanie elementów za pomocą metody splice()

Podobną do powyższej metody jest metoda splice(od, ile_wyciąć, elementy_wstawiane). Podstawowa różnica jest taka, że metoda splice modyfikuje tablicę na której jest wywoływana.
Parametr ile_wyciąć mówi ile elementów powinno być usuniętych z tablicy. Jeżeli podamy 0, wtedy nic nie zostanie z tablicy usunięte. Opcjonalne parametry elementy_wstawiane to elementy, które po usunieciu danego elementu z tablicy, zostaną na jego miejsce wstawione. Podajemy je jeden po drugim. Metoda ta zmienia tablicę na której została wywołana:


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];

ourTable.splice(1, 1);
console.log(ourTable); //wypisze "Marcin, Agnieszka"

ourTable.splice(1, 1, 'Monika', 'Magda') //usuwam z wcześniejszego "Agnieszka" i wstawiam na jej miejsce inne panie
console.log(ourTable); //wypisze "Marcin, Agnieszka, Monika, Magda"

Usuwanie dowolnego elementu tablicy

Aby usunać jakiś element w tablicy wykorzystamy powyżej opisaną metodę splice:


    var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Monika'];
    var deletedElement = ourTable.splice(2, 1);
    console.log(ourTable); //wypisze 'Marcin', 'Ania', 'Monika'
    console.log(deletedElement); //wypisze 'Agnieszka'

Dodawanie elementu na koniec tablicy za pomocą metody push()

Metoda push() wstawia nowy element (lub kilka) do tablicy na jej końcu i zwraca długość nowej tablicy


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
console.log(ourTable.push('Grzegorz', 'Marta')); //wypisze 5

console.log(ourTable) //wypisze się "Marcin,Ania,Agnieszka,Grzegorz,Marta"

Usuwanie ostatniego elementu z tablicy przy pomocy metody pop()

Metoda pop() usuwa ostatni element tablicy, po czym go zwraca:


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
console.log(ourTable.pop()); //wypisze 'Agnieszka'

console.log(ourTable); //wypisze się "Marcin,Ania"

Dodawanie pierwszego elementu do tablicy za pomocą metody unshift()

Metoda unshift() wstawia nowy element do tablicy na jej początku, po czym zwraca nową długość tablicy


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
console.log(ourTable.unshift('Piotrek', 'Paweł')); //wypisze 5

console.log(ourTable); //wypisze się "Piotrek, Paweł, Marcin, Ania, Agnieszka"

Usuwanie pierwszego elementu z tablicy za pomocą metody shift()

Metoda shift() usuwa pierwszy element z tablicy i go zwraca:


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
ourTable.shift();

console.log(ourTable); //wypisze się "Ania,Agnieszka"

Dodanie elementu do tablicy w dowolnym miejscu

Tutaj tak samo musimy skorzystać z metody splice:


var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Monika'];
ourTable.splice(1, 0, 'Piotr'); //nic nie usuwamy, bo 0, a tylko dodajemy Piotra na indeksie 1.
console.log(ourTable); //'Marcin', 'Piotr', Ania', 'Agnieszka', 'Monika'

Wyszukiwanie elementu w tablicy

Tak samo jak w przypadku string, do wyszukiwania elementu możemy skorzystać z metody indexOf():


var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Monika'];
if (ourTable.indexOf('Ania') !== -1) {
    console.log('Ania występuje w tablicy');
}

Pętla po tablicy za pomocą forEach()

Jak już poznaliśmy w rozdziale o pętlach oraz powyżej najprzyjemniejszym sposobem przechodzenia po wszystkich elementach tablicy jest forEach(element, index):


var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Piotrek', 'Grześ', 'Magda'];
ourTable.forEach(function(el, i) {
    console.log(el, i); //wypisze kolejno elementy tablicy np. Marcin 0, Ania 1...
});

Funkcja forEach mimo prostoty użycia, ma jeden problem.
Tak odpalonej pętli nie jesteśmy w stanie przerwać. Jeżeli chcesz wykonać podobną pętlę, którą możesz przerwać, skorzystaj z funkcji every():

Pętla po tablicy za pomocą every() i some()

Pętla za pomocą every() jest podobna do pętli forEach(), z tym że, za każdą iteracją musi zwracać prawdę albo fałsz. Jeżeli zwrócona zostanie false (lub coś co zostanie niejawnie przekonwertowane na false), pętla zostanie przerwana zwracając false:


['a', 'b', 'c'].every(function(el, index) {
    //...
    // Do your thing, then:
    // ...

    if (you_want_to_break) {
        return false;
    } else {
        return true;
    }
})

//np

var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Piotrek', 'Grześ', 'Magda'];
ourTable.every(function(el, i) {
    console.log(el, i);

    if (el == 'Piotrek') { //Przerwij pętlę gdy element == "Piotrek"
        return false;
    } else {
        return true;
    }
});

Bardzo podobna do every() jest pętla wykonana za pomocą funkcji some().
W tym przypadku pętla jest kończona, gdy natrafi na pierwszy pasujący do warunku element (czyli zostanie zwrócone true):


['a', 'b', 'c'].every(function(el, index) {
    //...
    // Do your thing, then:
    // ...

    if (you_want_to_break) {
        return true;
    } else {
        return false;
    }
});

//np

var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Piotrek', 'Grześ', 'Magda'];
ourTable.some(function(el, i) {
    console.log(el, i);

    return (el == 'Agnieszka'); //przerwij gdy element == "Agnieszka"
});

Pętla po tablicy z modyfikacją za pomocą map()

Bardzo podobną do forEach w użyciu jest metoda map. Tak samo jak powyższa robi ona iterację po elementach tablicy. Różnicą jest to, że każdorazowo wykonuje ona zadane operacje (jakąś funkcję) na danym elemencie tablicy zwracając go. W wyniku więc zwracana jest tablica o takiej samej liczbie elementów, ale już ze zmodyfikowanymi elementami.
Map wykorzystuje się wtedy, gdy chcemy wywołać jakąś funkcję dla każdego z elementów tablicy:


var ourTable = ['Marcin', 'Ania', 'Agnieszka'];
var ourTable2 = ourTable.map(function(el, i) {
    return el + ' ' + i;
});
console.log(ourTable); //wypisze [Marcin, Ania, Agnieszka]
console.log(ourTable2); //wypisze [Marcin 0, Ania 1, Agnieszka 2]

var ourTable = [1, 2, 3];
var ourTable2 = ourTable.map(function(el, i) {
    return el * 2;
});

console.log(ourTable2); //wypisze [2, 4, 6]

var numbers = [1.2, 4.5, 9.3];
console.log(numbers.map( Math.ceil )); //wypisze [2, 5, 10]

function x3(number) {
    return number * 3;
}

var ourTable = [1, 2, 3];
console.log(ourTable.map(x3)); //wypisze [3, 6, 9]

Filtrowanie elementów za pomocą filter()

Bardzo często będziemy chcieli przefiltrować daną tablicę zwracając tylko elementy, które pasują do danego warunku. Moglibyśmy to zrobić klasycznie za pomocą for czy powyższych funkcji - stworzylibyśmy dodatkową tablicę i w pętli wstawialibyśmy do niej pasujące elementy. Da się tak - ale o wiele przyjemniej jest skorzystać z funkcji filter().
Funkcja filter() robi pętlę po danej tablicy i w wyniku zwraca nową tablicę, która zawiera wszystkie elementy, przy których zostało zwrócone true:


var ourTable = [1, 2, 3, 4, 5, 6];
var evenNumbers = ourTable.filter(function(el, i) {
    return el % 2 == 0;
});

console.log(evenNumbers); // wypisze tablicę [2,4,6]

var ourTable = ['Marcin', 'Ania', 'Agnieszka', 'Monika', 'Piotrek'];
var woman = ourTable.filter(function(el, i) {
    return (el.charAt(el.length-1) == 'a')
});

console.log(woman); //wypisze tablicę ["Ania", "Agnieszka", "Monika"]