MooTools 1.2 - tablice w MooTools cz.2
08 lipca, 2008
W drugiej i ostatniej części kursu poświęconej metodom obiektu Array jakie oferuje nam MooTools 1.2 zajmiemy się rozszerzaniem tablicy o wiele elementów naraz (metody extend i combine), usuwaniu tablic zagnieżdżonych (metoda flatten), tworzeniem obiektów (a właściwie hashy) na bazie tablic (metody associate i link) oraz konwersjami kolorów z formatu RGB na heksadecymalny i odwrotnie.
Gdy push i include nie wystarczają
Nieraz podczas programowania zdarzy się sytuacja w której będziemy potrzebować dodać do istniejącej tablicy kilka elementów naraz. Oczywiście można zrobić to w pętli i wykorzystać chociażby metodę push. Jednak po co zapisywać zbędny kod, jeżeli możemy zrobić to za pomocą jednej krótkiej linijki - dzięki metodzie extend:
[1, 2, 3, 4, 5].extend([5, 6, 7, 8, 9, 10]);
Jak widać metoda extend pobiera jeden argument - tablicę do scalenia z istniejącą już tablicą. W efekcie działania tej metody otrzymamy następującą tablicę:
[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]
Widać, że nastąpiło powielenie elementu o wartości 5. Dzieje się tak dlatego, ponieważ metoda extend bazuje na innej metodzie obiektu Array - metodzie push. Gdybyśmy chcieli jednak uzyskać efekt podobny do działania metody include (czyli brak możliwości powielenia elementu dodawanego w tablicy wynikowej), to musimy skorzystać z metody bazującej na include, czyli metody combine:
[1, 2, 3, 4, 5].combine([5, 6, 7, 8, 9, 10]);
W rezultacie uzyskamy tablicę:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Która posiada unikalne elementy.
Podsumowując ten fragment - odpowiednikiem metody push przy dodawaniu kilku elementów naraz do danej tablicy jest metoda extend, a w wypadku metody include jest to metoda combine.
Usuwanie zagnieżdżonych tablic
Gdyby zaszła potrzeba zamiana tablicy postaci (nie ukrywajmy - lekko zagmatwanej):
[[1, [2, [3, 4, [5, [6, [7]]], 8, 9, 10]]], [[[[11]], [12]]]]
Na tablicę zawierającą elementy o wartościach od 1 do 12, bez żadnych zagnieżdżonych tablic, to możemy skorzystać z metody flatten:
[[1, [2, [3, 4, [5, [6, [7]]], 8, 9, 10]]], [[[[11]], [12]]]].flatten();
W wyniku jej działania uzyskamy nową, o wiele czytelniejszą formę wspomnianej tablicy:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Tworzymy obiekty na bazie tablic
Jak pewnie wiecie obiekty składają się z par właściwość-wartość, dlatego też przydatna może niektórym wydać się możliwość stworzenia obiektu z dwóch tablic, z których jedna zawiera właściwości, a druga wartości - taką metodą jest associate:
tablicaWartosci.associate(tablicaWlasciwosci);
Na przykład stwórzmy obiekt w którym każdej właściwości będzie odpowiadał kwadrat jej wartości:
[1, 2, 9, 16, 25].associate([1, 2, 3, 4, 5]);
W rezultacie otrzymamy obiekt następującej postaci:
{ 1: 1, 2: 4, 3: 9, 4: 16, 5: 25 }
Czasem może się okazać, że znamy typ poszczególnych właściwości obiektu i potrzebujemy im przypisać na bazie tablicy wartości danego typu. Do tego celu służy metoda link:
tablicaWartosci.link(obiektWzorzecDopasowan);
W powyższym zapisie tablicaWartosci to po prostu tablica z elementami (z reguły różnych typów), a obiektWzorzecDopasowan to obiekt, gdzie wartości poszczególnych właściwości określają typu obiektów natywnych. Na przykład: jeżeli chcemy w danym miejscu umieścić cyfrę zapisujemy Number.type, jeżeli ma być to ciąg znaków zapisujemy String.type itd.
[1,2,3,'a','b'].link({ "Liczba testowa" : Number.type, "Znak testowy" : String.type });
W rezultacie otrzymamy obiekt postaci:
{ "Liczba testowa" : 1, "Znak testowy" : 'a' }
Co świadczy o tym, że wykorzystywane jest pierwsze dopasowanie do danego typu. Gdybyśmy chcieli dopasować wszystkie elementy tablicy, musimy stworzyć odpowiednią ilość właściwości:
[1,2,3,'a','b'].link({ "Jeden" : Number.type, "Litera a" : String.type, "Dwa" : Number.type, "Trzy" : Number.type, "Litera b" : String.type });
W rezultacie uzyskamy obiekt postaci:
{ "Jeden" : 1, "Litera a" : 'a', "Dwa" : 2, "Trzy" : 3, "Litera b" : 'b' }
Konwersje kolorów
Do omówienia pozostała nam jeszcze kwestia konwersi kolorów w formacie RGB na format heksadecymalny i odwrotnie. Służą do tego metody rgbToHex i hexToRgb.
Metoda rgbToHex operuje na tablicach trójelementowych oraz czteroelementowych- w zalezności od tego czy korzystamu z formatu RGB czy RGBA. Dodatkowo może ona pobierać jeden parametr, będący wartością logiczną, który pozwala określić czy metoda zwrócić obiekt typu String czy też tablicę:
[10, 20, 30].rgbToHex();
Powyższy kod zwróci nam:
"#0a141e"Gdybyśmy chcieli uzyskać ten sam kolor w postaci tablicy - zapiszemy:
[10, 20, 30].rgbToHex(true);
Uzyskując tym samym:
["0a", "14", "1e"]
Warto jeszcze wspomnieć, że jeżeli ustawimy wartość 0 dla parametru alpha koloru:
[10, 20, 30, 0].rgbToHex();
To usyskamy rezultat:
"transparent"Ale tylko i wyłącznie gdy ustawimy zwracanie rezultatu jako obiekt typu String, w przeciwnym wypadku uzyskamy zwykłą tablicę wartości heksadecymalnych.
Jeżeli chodzi o konwersję w drugą stronę to działa ona tak samo tylko musimy operować tablicy wartości heksadecymalnych:
["10", "20", "30"].hexToRgb(true);
Powyższy kod zwróci nam:
[16, 32, 48]
Natomiast po wykonaniu:
["10", "20", "30"].hexToRgb();
Otrzymamy ciąg znaków:
"rgb(16,32,48)"Podsumowanie
W ten oto sposób poznaliśmy wszystkie nowe możliwości obiektu Array jakie uzyskamy korzystając z MooTools. W kolejnej części kursu zajmiemy się obiektem natywnym Function.
Komentarze do wpisu "MooTools 1.2 - tablice w MooTools cz.2":
1.
Rafael napisał(a):
08 lipca 2008, 22:10:13
W zasadzie metoda Array.extend działa prawie tak samo jak natywna metoda Array.concat
var a=[1, 2, 3, 4], b=a.concat([5, 6, 7, 8]);Jedyna różnica polega na tym, że .extend modyfikuje oryginalną tablicę, a .concat zwraca nową tablicę stworzoną na podstawie oryginalnej i tablicy przekazanej jako argument i w dodatku ma więcej możliwości (można od razu dołączyć więcej tablic, czy całą listę pojedynczych wartości).
Swoją drogą dziwi mnie trochę fakt, że implementacja tej metody korzysta z pętli (okolice linii 483)
extend: function(array){ for (var i = 0, j = array.length; i < j; i++) this.push(array[i]); return this; },można to zapisać jedną instrukcją
extend: function(array){ this.push.apply(this,array); return this; },Przyznam się, że nie badałem sprawy, jest to tylko moja luźna opinia. Może był jakiś konkretny powód (wydajność? Ciężko uwierzyć)
2.
Dziudek napisał(a):
08 lipca 2008, 22:14:59
@Rafael – osobiście mam dwie teorie ;) Albo na jakiejś dziwnej przeglądarce typu IE6 to nie działało (choć cudów w tym kodzie nie ma, ale IE6 (a nawet IE7) na banalniejszych fragmentach się wykłada), albo też po prostu zespół MooTools niezbyt się przykładał do Natives – generalnie o ile pamiętam Natives to jedna z bardziej zaniedbanych sekcji w MooTools, bo dość rzadko ją aktualizowali ;)
3.
Rafael napisał(a):
08 lipca 2008, 22:47:31
Dla pewności sprawdziłem w standardzie ECMA-Scriptu, czy .push przyjmuje dowolnie długą listę argumentów .push(arg1, arg2, ..., argN) i rzeczywiście tak jest, więc nie jest to jakieś rozszerzenie Gecko, czy coś w tym stylu.
Przeprowadziłem szybki test. Wygląda na to, że jednak mamy do czynienia z sprawą wydajności, choć różnica czasowa nie była tak wielka. Z jednej strony, ciężko mi uwierzyć, że natywna metoda wywołana metodą apply działa wolniej od pętli+.push… ale po krótkim namyśle – jednak wywołanie .apply też coś kosztuje… trzeba w końcu całą tablicę przerobić na argumenty metody .push (nie wiem, jak to w silniku jest realizowane, ale na pewno coś na ten wzór) i w pętli wykonywanie czynności dodawania elementów.
Może jednak ta część Mootoolsa nie jest aż tak zaniedbana ;-P
4.
Dziudek napisał(a):
08 lipca 2008, 22:50:29
@Rafael – może nie jest zaniedbana, ale na pewno sprawia wrażenie takiej „jak dobrze działa to lepiej nie ruszajmy” :) Dzięki, że to zweryfikowałeś ;) Dla programistów MooTools jednak nawet te ułamki sekund robią różnicę zwłaszcza, że przy większej częstości użycia metody robią się z nich sekundy itd. ;)
Dodaj komentarz: