Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałEla Talaga Został zmieniony 11 lat temu
1
Kolekcje Collection Bag SequenceableCollection ArrayedCollection Array
ByteArray String Symbol Interval SequencedGrowableCollection OrderedCollection SortedCollection Set Dictionary Magnitude Association Te klasy definiują różne struktury danych. Kategorie metod: Przechodzenie (iterowanie) po elementach kolekcjii Szukanie konkretnego elementu w kolekcji Dodawanie i usuwanie elementów Pobieranie i zmienianie elementów Konwersje: asArray asBag asOrderedCollection asSet asSortedCollection każdy element <= następny asSortedCollection: sortBlock sortBlock określa porządek
2
Klasa Collection add: newElement dodaje nowy obiekt do kolekcji. Wynikiem jest wstawiony element! addAll: newElements dodaje wszystkie obiekty z newElements newElements do: [:each | self add: each]. ^newElements remove: oldElement ifAbsent: exceptionHandler remove: oldElement usuwa obiekt z kolekcji (wynikiem jest usuwany element, błąd gdy go nie ma) removeAll: aCollection usuwa kolekcję z kolekcji, wynikiem jest aCollection, błąd gdy któregoś elementu aCollection nie ma w odbiorcy) do: aBlock wykonuje aBlock dla każdego elementu z kolekcji select: aBlock wykonuje aBlock dla każdego elementu odbiorcy, tworząc nową kolekcję składającą się z tych elementów odbiorcy, dla których aBlock daje true. reject: aBlock podobnie, tworzy kolekcję z elementów, dla których aBlock daje false collect: aBlock wykonuje aBlock dla każdego elementu odbiorcy i daje nową kolekcję zawierającą elementy wyliczane przez blok (przetwarza elementy kolekcji tworząc z wynikowych wartości nową kol.) inject: initialValue into: operation wykonuje operację - dwuparametrowy blok - dla każdego elementu kolekcji jako drugiego argumentu, pierwszym jest wynik poprzedniej operacji (na początku initialValue) Np. #(1 2 3) inject: 1 into: [:acc :elt | acc+elt ] "daje 7" size liczba elementów odbiorcy isEmpty czy kolekcja jest pusta includes: anObject czy kolekcja (odbiorca) zawiera anObject occurrencesOf: anObject liczba wystąpień obiektu w odbiorcy
3
Klasa Collection c.d. Metody klasowe new with: anObject
with: firstObject with: secondObject ... withAll: aCollection np. OrderedCollection with: $4 with: ‘abc’ with: 8
4
SequenceableCollection (kolekcja indeksowana)
Worek (Bag) Rodzaj zbioru z powtórzeniami. Ma wszystkie metody klasy Collection. occurrencesOf: anObject liczba powtórzeń obiektu w worku size liczba elementów, razem z powtórzeniami do: aBlock obchodzi wszystkie elementy kolekcji Zbiór (Set) Kolekcja bez powtórzeń i bez porządku. Ma wszystkie metody klasy Collection, tzn. add: anObject dodaje obiekt (teoriomnogościowo) remove: anObject usuwa obiekt (ignorowane jeśli nie ma) remove: anObject ifAbsent: aBlock usuwa obiekt, jeżeli go nie ma, to wykonuje blok size liczba elementów w zbiorze includes: anObject czy element należy do zbioru do: aBlock wykonuje blok dla każdego elementu SequenceableCollection (kolekcja indeksowana) Klasa abstrakcyjna obejmująca kolekcje dające indeksowany dostęp do elementów. Indeksy wyznaczają porządek elementów w kolekcji. Oprócz metod z klasy Collection, są tu m. in. first pierwszy element kolekcji last ostatni element kolekcji at: anInteger element pod indeksem anInteger at: anInteger put: anObject wstawia obiekt na istniejącą pozycję anInteger Najważniejsze kolekcje indeksowane to Array (tablice), String (napisy), OrderedCollection (odpowiednik listy) i SortedCollection.
5
Kolekcja uporządkowana (OrderedCollection)
Może być użyta jako dynamiczna tablica, stos, lista lub kolejka. , aCollection daje uporządkowaną kolekcję powstałą przez połączenie dwóch kolekcji (SequenceableCollectio) add: anObject dodaje obiekt na koniec kolekcji add: newObject after: oldObject dodaje obiekt we wskazanym add: newObject before: oldObject miejscu (błąd gdy nie ma) addFirst: anObject dodaje obiekt na początek kolekcji addLast: anObject dodaje obiekt na koniec kolekcji after: anObject ifAbsent: aBlock before: anObject ifAbsent: aBlock daje obiekt występujący bezp. po (przed) anObject. Jeśli anObject nie występuje, lub jest ostatni (pierwszy) to wykonuje się aBlock. remove: anObject ifAbsent: aBlock usuwa obiekt z kolekcji removeFirst usuwa (i daje) pierwszy element (błąd gdy nie ma) removeLast usuwa (i daje) ostatni element (błąd gdy nie ma) do: aBlock wykonuje aBlock dla kolejnych elementów ponieważ dziedziczy z IndexedCollection, to ma metody: at: anInteger daje element występujący na pozycji anInteger at: anInteger put: anObject first daje pierwszy element last daje ostatni element
6
Kolekcja posortowana (SortedCollection)
Podklasa OrderedCollection sortBlock: aBlock tworzy nową kolekcję z określonym porządkiem new tworzy nową kolekcję z porządkiem <= Przykłady bloków sortujących: 1. sortowanie napisów według liczby samogłosek [ :a :b | (a asLowerCase select: [ :c | c isVowel ]) asSet size <= (b asLowerCase select: [ :c | c isVowel ]) asSet size ] 2. Kolejka priorytetowa - zakładamy, że elementy mają priorytet [ :a :b | a priorytet <= b priorytet ]
7
Słownik (Dictionary) Reprezentuje zbiór elementów dostępnych poprzez klucze. Elementami słownika są obiekty klasy Association - pary (klucz, wartość). Wartości mogą się powtarzać, ale klucze są niepowtarzalne. add: anAssociation dodaje nowy element - asocjację associationsDo: aBlock parametrem bloku będzie asocjacja Zalecane jest działanie raczej na wartościach i kluczach, a nie na asocjacjach: at: aKey daje wartość związaną z kluczem aKey. Daje nil, jeśli takiego klucza nie ma w słowniku. at: aKey ifAbsent: aBlock jeśli klucza nie ma, wykonuje ABlock at: aKey put: anObject wstawia parę (aKey, anObject) do słownika. Jeśli taki klucz już jest, to zmienia drugi element pary. do: aBlock wykonuje blok dla każdej wartości ze słownika keysDo: aBlock wykonuje blok dla każdej wartości ze słownika removeAssociation: anAssociation usuwa parę anAssociation removeKey: aKey ifAbsent: aBlock removeKey: aKey usuwa parę, której kluczem jest aKey keys daje kolekcję kluczy values daje kolekcję wartości size daje liczbę par w słowniku
8
Przykład użycia klasy Bag
Liczymy liczbę wystąpień słów na pliku. W wyniku wypisujemy listę słów (alfabetycznie) i liczbę ich wystąpień. | dane wystapienia wyniki slowo | dane := FileStream read: 'in.dat'. wyniki := FileStream write: 'out.dat'. wystapienia := Bag new. [(slowo := dane nextWord) isNil] whileFalse: [ wystapienia add: slowo asLowercase ]. wystapienia asSet asSortedCollection do: [ :word | wyniki nextPutAll: word; tab; nextPutAll: (wystapienia occurrencesOf: word) printString; cr ]. dane close. wyniki close.
9
Słownik - przykłady ksiazkaTelefoniczna := Dictionary new. ksiazkaTelefoniczna at: 'Ania' put: ' ' ; at: 'Jan' put: ' ' ; at: 'Basia' put: ' '. ksiazkaTelefoniczna at: 'Ania'. "--- numer telefonu Ani" ksiazkaTelefoniczna at: 'Tomek' ifAbsent: [^'brak danych']. Zbiór - przykłady Obliczamy zbiór znaków występujących w jednym pliku, a w drugim nie. | zb1 zb2 | zb1 := Set new. zb2 := Set new. (FileStream read: 'file1.txt') do: [ :zn | zb1 add: zn ]. (FileStream read: 'file2.txt') do: [ :zn | zb2 add: zn ]. ^zb1 reject: [ :zn | zb2 includes: zn ]
10
Reprezentacja grafu Graf = zbiór wierzchołków
Każdy wierzchołek grafu ma jakąś informację (etykietę) i uporządkowaną kolekcję (OrderedCollection) lub zbiór (jeżeli porządek jest nieistotny) wierzchołków będących sąsiadami. Jeżeli krawędzie grafu mają być etykietowane (np. jak w automacie), to można zamiast uporządkowanej kolekcji użyć słownika, którego kluczami będą etykiety, a wartościami wierzchołki grafu (sąsiedzi). Zaznaczanie wierzchołków przy obchodzeniu grafu można zrobić przez przechowywanie zbioru zaznaczonych wierzchołków.
11
Obchodzenie grafu wszerz
Decydujemy się na dostęp do węzłów grafu także poprzez ich etykiety. Graf musimy zatem reprezentować jako słownik, którego kluczami są etykiety (napisy), a wartościami węzły. Object subclass: #Graf instanceVariableNames: ' wezly' classVariableNames: '' poolDictionaries: '' węzły - słownik węzłów (coś w rodzaju tablicy węzłów indeksowanej etykietami) Klasa definiująca węzły grafu. Dowiązania do sąsiadów są reprezentowane przez zbiór dowiązania. Object sublass: #Węzeł instanceVariableNames: ‘ etykieta dowiązania’ “Metody klasowe “ with: aString “Tworzy nowy węzeł o etykiecie aString” ^self new initialize: aString “Metody egzemplarzowe” initialize: aString etykieta := aString. dowiązania := Set new. etykieta ^etykieta dołącz: węzeł dowiązania add: węzeł
12
Object sublass: #Graf instanceVariableNames: ‘ węzły’ classVariableNames: ‘‘ poolDictionaries: ‘‘ “Metody klasowe “ new ^super new initialize “Metody indywidualne” initialize węzły := Dictionary new dodaj: et “Dodajemy do grafu węzeł o etykiecie et i przekazujemy jako wynik. Jeśli węzeł o takiej etykiecie już istniał, to jest wynikiem” | nowy | ^węzły at: et ifAbsent: [ nowy := Węzeł with: et . węzły at: et put: nowy. ^nowy ] dodajWęzeł: węzeł “Dodaje już gotowy węzeł do grafu, jeżeli nie ma jeszcze węzła o takiej samej etykiecie; wpp. błąd “ (węzły includesKey: węzeł etykieta) ifTrue: [ ^self error: ‘powtórzona etykieta’] ifFalse: [ węzły at: (węzeł etykieta) put: węzeł. ^węzeł ] połącz: et1 z: et2 (dodaj: et1) dołącz: (dodaj: et2) połączWęzeł: w1 z: w2 (dodajWęzeł: w1) dołącz: (dodajWęzeł: w2)
13
Przykład użycia: obejdźWszerz: startEt wykonując: aBlock
“Obchodzi graf wszerz począwszy od węzła o etykiecie startEt, dla każdego węzła wykonując aBlock “ ^self obejdźOdWęzła: (węzły at: startEt ifAbsent: [ ^self error: ‘nie ma takiego węzła’] ) wykonując: aBlock obejdźOdWęzła: start wykonując: aBlock “ Obchodzi graf wszerz, startując od węzła start.” | kolejny zaznaczone kolejka | zaznaczone := Set new. kolejka := OrderedCollection new. kolejka addLast: start. zaznaczone add: start. [ kolejka isEmpty ] whileFalse: [ kolejny := kolejka removeFirst . (kolejny dowiązania) do: [ : w | (zaznaczone includes: w) ifFalse: [ kolejka addLast: w . zaznaczone add: w ] . aBlock value: kolejny ] Przykład użycia: graf := Graf new. graf połącz: ‘A’ z: ‘B’; połącz: ‘A’ z: ‘C’; połącz: ‘C’ z: ‘A’; połącz: ‘A’ z: ‘D’; połącz: ‘C’ z: ‘D’. graf dodaj: ‘X’; dodaj ‘Y’. graf obejdźWszerz: ‘A’ wykonując: [ : w | w etykieta out ]
14
Przykład - Network (graf)
Sieć (Network) rozumiemy jako kolekcję wierzchołków jakoś ze sobą powiązanych. Object sublass: #Network instanceVariableNames: ‘connections’ classVariableNames: ‘‘ poolDictionaries: ‘‘ Zmienne egzemplarzowa connections jest słownikiem powiązań między wierzchołkami. Kluczami w tym słowniku są wierzchołki, wartościami są zbiory wierzchołków powiązane z wierzchołkiem określonym przez klucz. A C D B Elementem słownika connections, czyli parą (klucz, wartość) będzie ( wierzchołek A, zbiór { B, C, D } ) “Metody klasowe klasy Network” new ^ super new initialize “Metody egzemplarzowe klasy Network” connect: nodeA to: nodeB "Dodajemy powiązanie między wierzchołkiem A i B." (connections at: nodeA ifAbsent: [connections at: nodeA put: Set new]) add: nodeB. at: nodeB ifAbsent: [connections at: nodeB put: Set new]) add: nodeA
15
initialize "Inicjalizacja sieci." connections := Dictionary new printOn: aStream "Wypisujemy graf na strumień." connections keys asSortedCollection do: [ :node | node printOn: aStream. (connections at: node) asSortedCollection do: [ :neighbor | aStream cr; nextPutAll: ' >> '. neighbor printOn: aStream]. aStream cr] Chcemy znaleźć taką drogę w sieci pomiędzy dwoma wierzchołkami, która nie prowadzi przez wierzchołki należące do danego zbioru. pathFrom: nodeA to: nodeB avoiding: nodeSet " Znajdujemy drogę od wierzchołka A do wierzchołka B nie prowadzącą przez wierzchołki ze zbioru nodeSet. Wynikiem jest nowa sieć (też obiekt klasy Network )”. | answer | nodeSet add: nodeA. (connections at: nodeA ifAbsent: [^nil]) do: node = nodeB ifTrue: [ ^Network new connect: nodeA to: node]. (nodeSet includes: node) ifFalse: [ answer := self pathFrom: node to: nodeB avoiding: nodeSet. answer isNil ifFalse: [ ^answer connect: nodeA to: node]]]. ^nil
16
Object sublass: #NetworkNode
instanceVariableNames: ‘ name ‘ classVariableNames: ‘‘ poolDictionaries: ‘‘ “Metody egzemplarzowe klasy NetworkNode” <= aNode “Porównujemy nazwy” ^ name <= aNode name name ^name name: aString name := aString printOn: aStream aStream nextPutAll: ‘Node (‘, name, ‘)’
17
Strumienie (Streams) Strumienie służą m.in. do komunikowania się
programu z otoczeniem. Object Stream (abstr) Random SequencedStream (abstr) PositionalbleStream (abstr) ReadStream WriteStream ReadWriteStream FileStream File (to już nie jest klasa strumieni) Zawartość strumieni jest (zwykle) przechowywana w postaci kolekcji.
18
Stream Realizuje pojęcie strumienia sekwencyjnego
atEnd czy koniec strumienia (abstr) next daje następny obiekt ze strumienia (abstr) do: aBlock wykonuje blok dla każdego pozostałego elementu strumienia skipTo: anObject przeskakuje za kolejne wystąpienie zadanego obiektu, informuje czy się udało contents daje kolekcję będącą zawartością strumienia (abstr) do: aBlock [self atEnd] whileFalse: [aBlock value: self next] skipTo: anObject [self atEnd] whileFalse: [self next = anObject ifTrue: [^true]]. ^false
19
SequencedStream nextWord | wordStream element |
self skipSeparators ifFalse: [^nil]. wordStream := self contentsSpecies writeStream: 32. "32-elementowa tablica, wymieniana gdy za mała" [self atEnd] whileFalse: [element := self next. element isSeparator ifTrue: [^wordStream contents]. wordStream nextPut: element]. ^wordStream contents skipWhile: aOneArgBlock [self atEnd] whileFalse: [ (aOneArgBlock value: self next) ifFalse: [self pop. ^true]]. ^false
20
PositionableStream Realizuje strumień pozwalający zmieniać
bieżącą pozycję on: aCollection Klasowa, tworzy nowy strumień oparty na aCollection position daje bieżącą pozycję position: anInteger ustawia pozycję isEmpty czy strumień pusty
21
WriteStream Realizuje strumień z zapisywaniem nextPut: anObject
dopisuje obiekt jako następny element kolekcji nextPutAll: aCollection dopisuje kolekcję aCollecion do strumienia i daje ją jako wynik Double dispatch: nextPutAll: aCollection ^aCollection appendToStream: self Collection>>appendToStream: puttableStream self do: [ :element | puttableStream nextPut: element ]
22
ReadStream ReadWriteStream
Realizuje zwykły strumień (praktycznie nie ma własnych metod). ReadWriteStream Realizuje strumień do czytania i pisania (praktycznie nie ma własnych metod).
23
Random Realizuje strumień liczb pseudolosowych
new Klasowa, tworzy nowy generator (uwaga - zainicjowany na podstawie zegara systemowego) next daje kolejną liczbę pseudolosową [0..1[. zaimplementowaną w podklasach seed: anInteger inicjalizuje generator atEnd zawsze daje false contents powoduje błąd Właściwie jest abstrakcyjna, ale r := Random new. działa, bo daje obiekt domyślnej podklasy.
24
Strumienie plikowe Klasy związane z plikami: File
Tworzenie nowego obiektu klasy FileStream: on: aFile read: aString readWrite: aString write: aString write: fileId mode: mode check: check type: fileType (p. opis w Dolphinie) Metody klasy FileStream: close zamyka plik flush nie zamyka, ale zapisuje zawartość bufora na dysku File>>open: aString File>>open: aString mode: modeSymbol check: aBoolean share: shareSymbol (p. Opis w Dolphinie)
25
Przykład - baza danych plików
Klasa WordIndex pozwala na utworzenie bazy danych dokumentów, umożliwiającej szybkie odszukanie wszystkich dokumentów zawierających pewne słowa. Zakładamy, że dokumenty są plikami tekstowymi zawierającymi słowa (ciągi znaków alfanumerycznych oddzielonych innymi znakami). Używamy bazy danych zadając jej pytanie zawierające kolekcję słów; w odpowiedzi otrzymujemy kolekcję nazw (ścieżek) dokumentów zawierających wszystkie te słowa. Np. chcemy znaleźć wszystkie dokumenty zawierające “programowanie obiektowe”. Obiekty tej klasy (bazy danych) będą miały dwa atrybuty: documents - zbiór napisów reprezentujących ścieżki do plików, których słowa są umieszczone w indeksie words - indeks słów, słownik, którego kluczami są słowa, a wartościami ścieżki do dokumentów zawierających te słowa Object subclass: #WordIndex instanceVariableNames: 'documents words ' classVariableNames: '' poolDictionaries: '' “Metody klasowe klasy WordIndex” new ^ super new initialize “Metody indywidualne klasy WordIndex” initialize "Inicjalizacja pustego indeksu." documents := Set new. words := Dictionary new
26
addWord: wordString for: pathName
"Dodaje wordString do słownika words dla dokumentu opisanego przez pathName." (words includesKey: wordString) ifFalse: [words at: wordString put: Set new]. (words at: wordString) add: pathName addDocument: pathName "Dodaje wszystkie słowa dokumentu opisanego przez pathName do słownika words." | word wordStream | “Jeżeli dokument o tej nazwie już tu jest, to usuwamy go i odwołania do niego ze słownika words” (documents includes: pathName) ifTrue: [self removeDocument: pathName]. “Otwieramy plik” wordStream := FileStream read: pathName. documents add: pathName. [(word := wordStream nextWord) == nil] whileFalse: [ self addWord: word asLowerCase for: pathName]. wordStream close removeDocument: pathName "Usuwamy dokument o nazwie pathName ze słownika words” words do: [ :docs | docs remove: pathName]. self removeUnusedWords removeUnusedWords "Usuwamy wszystkie słowa, które mają puste zbiory dokumentów." | newWords | newWords := Dictionary new. words associationsDo: [ :anAssoc | anAssoc value isEmpty ifFalse: [newWords add: anAssoc]]. words := newWords
27
Przykład użycia: locateDocuments: queryWords
"Daje tablicę nazw (ścieżek) plików wszystkich dokumentów zawierających wszystkie słowa w kolekcji queryWords." | answer bag | bag := Bag new. answer := Set new. queryWords do: [ :word | bag addAll: (words at: word ifAbsent: [#()])]. "bag zawiera wszystkie ścieżki dokumentów zawierających którekolwiek słowo" "do answer wstawiamy tylko nazwy plików, które zawierają wszystkie szukane słowa" bag asSet do: [ :document | queryWords size = (bag occurrencesOf: document) ifTrue: [answer add: document]]. ^answer asSortedCollection asArray Przykład użycia: Index := WordIndex new. Index addDocument: 'pierwszy.txt'. Index addDocument: 'drugi.txt'. ..... oop := Index locateDocuments: #('klasa' 'obiekt' 'metoda'). oop do: [ :name | name out ].
28
Kolekcje a tożsamość obiektów
Przypomnienie: = i ==, hash Co wstawiamy do kolekcji: wartości czy obiekty?
29
Association>>hash:
^ key hash Association>>= anAssociation ^self species == anAssociation species and: [key = anAssociation key and: [value = anAssociation value]] Set>>includes: target ^(self basicAt: (self findElementOrNil: target)) notNil Set>>findElementOrNil: anObject | capacity index element | capacity := self basicSize. index := self hash: anObject max: capacity. [(element := self basicAt: index) isNil or: [anObject = element]] whileFalse: [index := index \\ capacity + 1]. ^index
30
c.d. OrderedColelction>>includes: target firstIndex to: lastIndex do: [:i | (self basicAt: i) = target ifTrue: [^true]]. ^false
31
Standard NCITS J20 Draft of ANSI Smalltalk (Dec 1997, ver. 1.9)
Podsumowanie (p ): Niektóre implementacje kolekcji mogą używać wartości haszujących (metoda hash) przechowywanych obiektów i/lub ich kluczy. Jeśli te wartości haszujące ulegną zmianie, to zachowanie kolekcji jest niezdefiniowane do momentu wykonania metody rehash kolekcji.
32
Przykład as1 := Association key: 10 value: 'Ala'.
as2 := Association key: 12 value: 'Ola'. c := SortedCollection new. s := Set new. c add: as1. c add: as2. s add: as1. s add: as2. Transcript show: c printString; cr. Transcript show: s printString; cr. Transcript show: (c includes: as1) printString; cr. Transcript show: (s includes: as1) printString; cr. Transcript show: '#', as1 hash printString; cr. as1 key: 134. Transcript show: (c includes: as1) printString;cr. s rehash. c rehash.
33
Przykład c.d. (Dolphin 5.1) a SortedCollection(10 -> 'Ala' 12 -> 'Ola') a Set(12 -> 'Ola' 10 -> 'Ala') true #10 a SortedCollection(134 -> 'Ala' 12 -> 'Ola') a Set(12 -> 'Ola' 134 -> 'Ala') false #134
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.