Metoda .sort() w JavaScript jako wprowadzenie do programowania funkcyjnego

Wpis ten ma za zadanie wyjaśnić zasadę działania funkcji sortującej, która jest dostępna dla obiektu Array. Pozwala ona sortować dowolne elementy dodane do tablicy. Wszystko dzięki przekazywanej jako parametr funkcji, która definiuje nam co chcemy ze sobą porównać. Takie rozwiązanie (funkcja jako parametr) jest stosowane w programowaniu funkcyjnym, które staje się bardzo popularne.

Jeśli jesteś zainteresowana/ny czym jest (teoretycznie) programowanie funkcyjne to odsyłam Cię do wikipedii oraz wikibooks, gdzie można przeczytać trochę na ten temat. Po tym wprowadzeniu możemy przejść już do konkretów.

Funkcja wyższego rzędu

Funkcja wyższego rzędu (ang. higher-order function) zwana też czasami funkcją wyższego stopnia to funkcja, która jako parametr przyjmuje funkcje lub zwraca inną funkcję. W naszym przykładzie taką funkcją jest właśnie metoda .sort().

Choć domyślnie nie musi ona przyjmować jako parametr funkcji (patrz przykład niżej) to jak zaprezentuje później może to być bardzo przydatne.

// tworzę pustą tablicę
var arr = [];
// dodaję 4 elementy do tablicy
arr.push('c', 'd', 'a', 'b');
// sortuję tablicę
arr.sort();

console.log(arr); // ['a', 'b', 'c', 'd']

Pamiętajmy, że metoda .sort() domyślnie sortuje elementy wg. porządku alfabetycznego. To oznacza, że kolejność elementów 1, 22, 2, 11 będzie się prezentować w taki sposób: 1, 11, 2 , 22.

Metoda .sort() z parametrem

Teraz chcielibyśmy posortować elementy w innej kolejności niż alfabetycznie (i nie koniecznie rosnąco) – co wtedy? Wtedy korzystamy z uroków programowania funkcyjnego, gdzie sam algorytm sortowania jest zaimplementowany w silniku JS (w jaki sposób o tym innym razem), a my jedynie decydujemy co chcemy porównywać.

Sortowanie wg. ilości znaków w string-u

Jak czytamy w dokumentacji MDN, parametr przyjmuje funkcję, która sama przyjmuje dwa parametry (ich nazwa jest dowolna, ważna jest kolejność tj. pierwszy i drugi parametr). Zadeklarujmy sobie tą funkcję.

function compareLength(a, b) {
    return a.length - b.length
}

W moim przypadku zdefiniowałem sobie dwa parametry tj. a i b. Przyjmuję, że oba parametry mają właściwość length (zmienna typu string w tej właściwości przechowuje ilość znaków). Następnie zwracam za pomocą return różnicę wartości tej właściwości dla obu parametrów.

Przyjrzyjmy się działaniu kodu z wykorzystaniem naszej funkcji compareLength(), a potem będę wyjaśniał resztę.

function compareLength(a, b) {
    return a.length - b.length
}       
        
// tworzę pustą tablicę
var arr = [];
// dodaję 4 elementy do tablicy
arr.push('ccc', 'd', 'aa', 'bbbb');
// sortuję tablicę, UWAGA!!! Parametrem jest tylko nazwa, bez wywołania!
arr.sort(compareLength);

console.log(arr); // ['d', 'aa', 'ccc', 'bbbb']

Tym razem efekt sortowania to ciągi znaków od najkrótszego (najmniej liczebnego) do najdłuższego. Dlaczego tak się stało? Otóż w zależności od tego co zwróci funkcja compareLength() to sortowanie będzie wyglądać inaczej tz.:

  • jeśli zwróci wartość mniejszą od 0 – indeks elementu a będzie mniejszy niż indeks b,
  • jeśli zwróci 0 – pozostawia a oraz b w niezmienionej kolejności względem siebie,
  • jeśli zwraca wartość większą od 0 – indeks elementu a będzie większy niż indeks elementu b

Sortowanie bąbelkowe

O co chodzi z tym indeksem? Indeks to pozycja danego elementu w naszej tablicy, natomiast parametry a i b to elementy w tablicy, które porównujemy. Porównajmy ze sobą ‚ccc’ i ‚d’

‚ccc’.length -> 3, ‚d’.length -> 1 czyli 3-1 = 2.

Dla tych parametrów funkcja zwróciła nam wartość większą od zera więc indeks elementu a (‚ccc’) będzie większy od elementu b (‚d’). Czyli nasza tablica będzie wyglądać inaczej tj.: [‚d’, ‚ccc’, ‚aa’, ‚bbbb’]. W ten sposób będziemy porównywać wszystkie elementy w tablicy, aż do momentu porównania wszystkich elementów.

Tego typu algorytm jest nazywany sortowaniem bąbelkowym. Jeśli chcesz dokładnie zapoznać się z tym algorytmem odsyłam Cię do strony eduinf.waw.pl, gdzie znajdziesz dokładny opis algorytmu oraz różne sposoby jego optymalizacji.

Sortowanie wg. wybranej właściwości obiektu

Tym razem mamy 3 obiekty (docelowo może być ich dowolna ilość). Każdy z obiektów ma właściwość name i score. Możemy przyjąć, że dane te pobraliśmy z bazy danych typu Firebase (jak to zrobić możesz dowiedzieć się ze wpisu na temat Firebase Realtime Database).

var arr = [];
        
var obj1 = {name: 'Mateusz', score: 12};
arr.push(obj1);
        
var obj2 = {name: 'Marek', score: 22};
arr.push(obj2);
        
var obj3 = {name: 'Michał', score: 4};
arr.push(obj3);

Teraz stworzymy funkcję, która będzie nam porównywać właściwość score. Ponieważ parametrami w funkcji, którą będziemy przekazywać do .sort() będą tym razem nasze obiekty to wartości tej właściwości będziemy porównywać.

function compareScore(a, b) {
    return a.score - b.score;
}

Mając już funkcję możemy ją wykorzystać do sortowania. Zobaczmy jak się całość prezentuje.

var arr = [];
        
var obj1 = {name: 'Mateusz', score: 12};
arr.push(obj1);
        
var obj2 = {name: 'Marek', score: 22};
arr.push(obj2);
        
var obj3 = {name: 'Michał', score: 4};
arr.push(obj3);
        
function compareScore(a, b) {
    return a.score - b.score;
}
        
arr.sort(compareScore);
        
console.log(arr); /*
[
    {name: 'Michał', score: 4}, 
    {name: 'Mateusz', score: 12}, 
    {name: 'Marek', score: 22}
]
*/

Dzięki tak prostemu rozwiązaniu mamy malejąco posortowane wyniki względem właściwości score. Jeśli chcemy odwrócić sortowanie wystarczy zamienić kolejność działania w naszej funkcji – zobaczmy:

function compareScore(a, b) {
    return b.score - a.score;
}

Mam nadzieje, że teraz już metoda .sort() jest dla Ciebie jasna. Wykorzystywanie jej jest bardzo przydatne i dość łatwe. To właśnie zalety programowania funkcyjnego. Niestety wszystko ma swoją drugą stronę medalu. Wydajność tego rozwiązania nie jest powalające jednak jego użyteczność rekompensuje to.

Implementacja metody .sort()

Jeśli jesteś ciekawy jak JS implementuje programowanie funkcyjne to zapraszam do mojego wpisu o tytule: Implementacja metody .sort() w JavaScript

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

*

*

20 − four =