Iteracje po kolekcji

W języku Smalltalk iteracje są realizowane za pomocą metod wysyłanych do kolekcji.

Iteracja – metoda do:

Metoda do: jest podstawową metodą iteracyjną kolekcji na której oparte są inne tego typu metody. Programiści innych języków piszą najczęściej kod typu:

index := 1.
collection := #('Tomek' 'rower' 'Witaj').
[index <= collection size] whileTrue: [
	[Transcript show: (collection at: index)]

Tymczasem powyższy kod można zapisać znacznie prościej i krócej przy użyciu metody do:

#('Tomek' 'rower' 'Witaj') do: [:each | Transcript show: each].

Powyższy kod wyświetla wszystkie elementy zawarte w kolekcji (zmienna each zawiera przy każdej iteracji kolejny element kolekcji). Jak widać z tego przykładu, metoda do: wykonuje zawartość bloku kodu będącego jej argumentem dla każdego elementu kolekcji z osobna.

Selekcja elementów - metoda select:

Metoda select: zwraca wszystkie elementy kolekcji spełniające warunek zawarty w bloku kodu będącego jej argumentem.

#( 1 2 55 4 8 29 13) select: [:each | each < 8].

Wynikiem wykonania powyższego kodu będzie kolekcja #(1 2 4).

Implementacja metody select: (i wielu innych metod iteracyjnych) wykorzystuje omówioną w poprzednim rozdziale podstawową metodę iteracyjną do:

select: aBlock 

	| newCollection |
	newCollection := self species new.
	self do: [:each |
             (aBlock value: each)
			ifTrue: [newCollection add: each]].
	^newCollection

Selekcja elementów - metoda reject:

Metoda reject: jest odwrotnością metody select: - zwraca ona wszystkie elementy kolekcji nie spełniające warunku zawartego w bloku kodu będącego jej argumentem.

#( 1 2 55 4 8 29 13) reject: [:each | each < 8].

Wynikiem wykonania powyższego kodu będzie kolekcja #(55 8 29 13).

Kolekcja wyników - metoda collect:

Metoda collect: zbiera wyniki kodu będącego jej argumentem wykonywanego na elementach kolekcji.

#(1 2 4 8 13) collect: [:each | each * 2].

Wynikiem wykonania powyższego kodu będzie następująca kolekcja #(2 4 8 16 26).

Inny przykład:

collectionOfSongs collect: [:each | each title].

Wynikiem wykonania powyższego kodu może być następująca kolekcja #(‘Czerwone korale’ ‘Kochaj mnie’ ‘Hej sokoły’).

Szukanie elementów – metody detect: i detect:ifNone:

Metoda detect: służy do szukania pierwszego elementu w kolekcji spełniającego warunek zawarty w kodzie bloku będącego jej argumentem.

#(4 2 8 3 9) detect: [:each | each < 3].

Wynikiem wykonania powyższego kodu będzie 2 (pierwszy element mniejszy od 3).

W przypadku, gdy żaden element w kolekcji nie spełnia warunku zdefiniowanego w bloku kodu będącym argumentem metody detect: wykonanie tej metody zakończy się błędem „Element not Found“ .

#(4 2 8 3 9) detect: [:each | each = 240].

Wykonanie powyższego kodu zakończy się błędem, ponieważ żaden element nie spełnia warunku zdefiniowanego w bloku kodu będącym argumentem metody detect:.

Jeżeli nie jesteśmy pewni, czy jakikolwiek element kolekcji spełni zadany warunek, to możemy użyć wariantu naszej metody – detect:ifNone:

#(4 2 8 3 9) detect: [:each | each = 240] ifNone: [nil].

Wynikiem wykonania powyższego kodu będzie nil. ponieważ kolekcja nie zawiera liczby 240.

Powyższy kod możemy w większości dialektów języka Smalltalk zapisać też bez słowa kluczowego nil:

#(4 2 8 3 9) detect: [:each | each = 240] ifNone: [].

Możemy też zwracać wartości różne od nil:

#(4 2 8 3 9) detect: [:each | each = 240] ifNone: [333].

Wynikiem wykonania powyższego kodu będzie 333.

Akumulacja wyników – metoda inject:into:

Metoda inject:into: jest odpowiednikiem funkcji wyższego rzędu fold (znanej także jako accumulate, reduce, compress lub inject) występującej w językach funkcyjnych. Przetwarza ona uporządkowaną kolekcję w celu zbudowania końcowego wyniku przy pomocy jakiejś funkcji łączącej elementy tej kolekcji.

Poniższy kod oblicza sumę dziesięciu pierwszych liczb całkowitych większych od zera.

(1 to: 10) inject: 0 into: [:sum :each | sum + each].

Wynikiem wykonania tego kodu będzie liczba 55.

Wartość początkowa może być dowolna.

(1 to: 10) inject: 45 into: [:sum :each | sum + each].

Wynikiem wykonania tego kodu będzie liczba 100 (45+55).

Poniżej trochę trudniejszy przykład:

„Uporządkowana kolekcja z trzema podkolekcjami typu Array.”
collection :=
        OrderedCollection
                with: #(1 2 3)
                with: #(3 4 5)
                with: #(3 6). 

„Dodajemy wszystkie elementy podkolekcji do nowej kolekcji Set”
collection
     inject: Set new
     into: [:result :each | result addAll: each; yourself].

Wynikiem wykonania tego kodu będzie Set (1 2 3 4 5 6). Liczba 3 występuje tutaj tylko jeden raz, poniewaz Set filtruje duplikaty.

Ilość elementów spełniających warunek – metoda count:

Metoda count: zwraca ilość elementów kolekcji spełniających warunek zdefiniowany w bloku kodu będącym argumentem tej metody.

#(1 7 4 3 9) count: [:each | each > 4].

Wynikiem wykonania tego kodu będzie 2, ponieważ tylko dwa elementy są większe od 4 (7 i 9).

Sprawdzanie obecności obiektu w kolekcji – metoda includes:

Metoda includes: sprawdza, czy jej argument znajduje się w kolekcji.

#(2 6 3 8 9) includes: 8.

Wynikiem wykonania tego kodu będzie wartość true Ponieważ kolekcja zawiera liczbę 8.

Sprawdzanie obecności elementu spełniającego warunek – metoda anySatisfy:

Metoda anySatisfy: sprawdza, czy kolekcja zawiera przynajmniej jeden element spełniający warunek zdefiniowany w bloku kodu będącym argumentem tej metody.

#(2 5 3 8 7) anySatisfy: [:each | each < 3].

Wynikiem wykonania tego kodu będzie wartość true ponieważ liczba 2 spełnia zadany warunek.

#(2 5 3 8 7) anySatisfy: [:each | each * 10 < 2].

Wynikiem wykonania tego kodu będzie wartość false ponieważ żadna liczba z kolekcji pomnożona przez dziesięć nie jest mniejsza od 2.

Przemysław Nieściór, 19.02.2016

What's new

  • Deploying Pier on Ubuntu with Plesk at the german provider 1blu
    28 February 201312:21:04 pm by Przemysław Nieściór
    This tutorial describes how to deploy Pier on an Ubuntu Linux distribution with Plesk at the german provider 1blu. It assumes that you want to install a pier image on an Ubuntu Linux with Apache 2 und...
  • Mechanizm switch-case w Smalltalku
    11 June 201212:00:43 pm by Przemysław Nieściór
    ENGLISH VERSION BELOW POLISH VERSION Język Smalltalk nie oferuje wraz ze swoimi standardowymi klasami odpowiednika mechanizmu switch-case, popularnego na przykład w językach wywodzących sie z języka...