====== Macierze komórkowe i struktury ======
* elementami macierzy są wartości tego samego typu (bool, int, double, char)
* struktury danych heterogeniczne - pozwalające gromadzić elementy róznych typów:
* **struktura** (//struct//) - wartości dostępne są w nazwanych **polach**
* **macierz komurkowa** (//cell array//) - wartości zorganizowane są w macierzy, elementy dostępne są za pomocą indeksów liczbowych
===== Komórka - obiekt typu cell =====
# komórka (cell) zawierająca liczbę calkowitą 42
a = { 42 }
# komórka (cell) zawierająca znak 'A'
b = { 'A' }
# komórka z napisem
c = { 'Siała baba mak' }
whos a b c
a =
{
[1,1] = 42
}
b =
{
[1,1] = A
}
c =
{
[1,1] = Siała baba mak
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 cell
b 1x1 1 cell
c 1x1 15 cell
Total is 3 elements using 24 bytes
===== Wektory i macierze komórkowe =====
# wektor komórkowey wierszowy
c = { 42, 'A', 1:3:10, 'Witaj'}
whos c
c =
{
[1,1] = 42
[1,2] = A
[1,3] =
1 4 7 10
[1,4] = Witaj
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
c 1x4 38 cell
Total is 4 elements using 38 bytes
# wektor kolumnowy
c = { 42; 'A'; 1:3:10; 'Witaj'}
size(c)
c =
{
[1,1] = 42
[2,1] = A
[3,1] =
1 4 7 10
[4,1] = Witaj
}
ans =
4 1
# macierz komórkowa 2x2
c = { 42, 'A'; 1:3:10, 'Witaj'}
size(c)
c =
{
[1,1] = 42
[2,1] =
1 4 7 10
[1,2] = A
[2,2] = Witaj
}
ans =
2 2
# elementami macierzy komórkowej moga być macierze komórkowe
d = { c , c ; 1, 'A'}
whos d
d =
{
[1,1] =
{
[1,1] = 42
[2,1] =
1 4 7 10
[1,2] = A
[2,2] = Witaj
}
[2,1] = 1
[1,2] =
{
[1,1] = 42
[2,1] =
1 4 7 10
[1,2] = A
[2,2] = Witaj
}
[2,2] = A
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
d 2x2 85 cell
Total is 4 elements using 85 bytes
===== Alokacja pustej macierzy komórkowej =====
* podobnie jak w przypadku zwykłych macierzy zalecane jest wczesniejsze zaalokowanie macierzy komórkowej (rozrzeczanie dynamiczen rozmiaru jest mniej efektywne)
* funkcja ''%%cell(N, M)%%'' tworzy pustą macierz komórkową o wymiarach ''%%NxM%%''
## pusta macierz - prealikacja macierzy komórkowej
x = cell(2, 3)
whos x
x =
{
[1,1] = [](0x0)
[2,1] = [](0x0)
[1,2] = [](0x0)
[2,2] = [](0x0)
[1,3] = [](0x0)
[2,3] = [](0x0)
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
x 2x3 0 cell
Total is 6 elements using 0 bytes
# ewentualnie można utworzyć macierz inicjując jej najdalszy element
y{2,3} = []
y =
{
[1,1] = [](0x0)
[2,1] = [](0x0)
[1,2] = [](0x0)
[2,2] = [](0x0)
[1,3] = [](0x0)
[2,3] = [](0x0)
}
**Ćwiczenie:** utwórz macierz komórkową o wymiarach 2x3 zawierającą 6 nastepujących elementów: * dzisiejsza data (zob. polecenie ''%%data%%'') * tablica 2-elementowa zawierająca aktualną godzinę i minutę (zob. polecenie ''%%clock%%'') * macierz jednostkowa o wymiarach 10x10 * napis “Witaj Świcie” * wektor wierszowy zawierający liczby calkowite od 1 do 100 * wektor 6 losowych liczb całkowitych z puli od 1 do 49 (wyniki losowanoa lotto) w kolejnosci rosnącej (zob. funkcję ''%%randi%%'')
===== Indeksowanie elementów obiektu typu cell =====
* nawiasy klamrowe ''%%{i, j}%%'' dają dostęp do wartości umieszczonych w komórkach
* nawiasy okrągłe ''%%(i, j)%%'' dają dostęp do komórek (wynik jest obiektem typu cell)
x = { 42, 'A'; 1:3:10, 'Witaj'};
% indeksowanie wartości (1,1)
a = x{1,1}
% indeksowanie komórek
b = x(1,1)
whos a b
a = 42
b =
{
[1,1] = 42
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 double
b 1x1 8 cell
Total is 2 elements using 16 bytes
x = { 42, 'A'; 1:3:10, 'Witaj'};
% elementem {2,1} jest wektor
a = x{2,1}
% element 1 wektora z komórki x{2,1}
c = x{2, 1}(1)
a =
1 4 7 10
c = 1
% elementem (2,1) jest komórka zawierająca wektor
b = x(2, 1)
% element 1 wektora znajdującago się w pierwszej komórce znajdującej się w x(2,1)
d = x(2, 1){1}(1)
whos a b c d
b =
{
[1,1] =
1 4 7 10
}
d = 1
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x4 24 double
b 1x1 24 cell
c 1x1 8 double
d 1x1 8 double
Total is 7 elements using 64 bytes
===== Ineksowanie za pomoca dwukropka : =====
x = { 42, 'A', 1:3:10, 'Matlab'};
# pierwsze 3 elementy - 3 różne zmienne ans
x{1:3}
ans = 42
ans = A
ans =
1 4 7 10
% wynik można podstawić do 3 róznych zmiennych
[a b c] = x{1:3}
whos a b c
a = 42
b = A
c =
1 4 7 10
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 double
b 1x1 1 char
c 1x4 24 double
Total is 6 elements using 33 bytes
% wynikiem x(1:3) nowa macierz komórkowa
x(1:3)
% wynikiem jest jedna zmienna
a = x(1:3)
whos a x
ans =
{
[1,1] = 42
[1,2] = A
[1,3] =
1 4 7 10
}
a =
{
[1,1] = 42
[1,2] = A
[1,3] =
1 4 7 10
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x3 33 cell
x 1x4 39 cell
Total is 7 elements using 72 bytes
% indeksowanie podobne jak w macierzach
x = { 42, 'A'; 1:3:10, 'Matlab'};
% pierwsza kolumna
a = x(1, :)
% ostatni wiersz
b = x(end, :)
a =
{
[1,1] = 42
[1,2] = A
}
b =
{
[1,1] =
1 4 7 10
[1,2] = Matlab
}
===== Wyświetlanie zawartości komórek =====
* ''%%celldisp()%%'' wypisuje zawartość kolejnych komórek
* ''%%cellplot()%%'' wypisanie wartości w trybie graficznym (w oknie), brak w Octave
x = { 42, 'A'; 1:3:10, 'Matlab'};
disp(x)
celldisp(x)
{
[1,1] = 42
[2,1] =
1 4 7 10
[1,2] = A
[2,2] = Matlab
}
x{1,1} =
42
x{2,1} =
1 4 7 10
x{1,2} =
A
x{2,2} =
Matlab
% wyświetlanie rekurencyjne macierzy komórkowych zawierających inne macierze komórkowe
y = {1, 2, x}
celldisp(y)
y =
{
[1,1] = 1
[1,2] = 2
[1,3] =
{
[1,1] = 42
[2,1] =
1 4 7 10
[1,2] = A
[2,2] = Matlab
}
}
y{1} =
1
y{2} =
2
y{3}{1,1} =
42
y{3}{2,1} =
1 4 7 10
y{3}{1,2} =
A
y{3}{2,2} =
Matlab
% celplot() nie jest dostępne w Octave
cellplot(x)
warning: the 'cellplot' function is not yet implemented in Octave
Please read to learn how you can
contribute missing functionality.
error: 'cellplot' undefined near line 2 column 1
===== Funkcje macierzowe =====
* wiele funkcji i operacji macierzowych działa również na macierzach komórkowych (np. ''%%reshape%%'', transpozycja)
* ''%%iscell()%%'' spradza, czy zmienna jest typu cell
x = { 42, 'A'; 1:3:10, 'Matlab'};
% rozmiar
[w k] = size(x)
% transpozycja
y = x'
w = 2
k = 2
y =
{
[1,1] = 42
[2,1] = A
[1,2] =
1 4 7 10
[2,2] = Matlab
}
% zmiana kształtu
reshape(x, [1, 4])
% usuwanie elementów
x(1, :) = []
ans =
{
[1,1] = 42
[1,2] =
1 4 7 10
[1,3] = A
[1,4] = Matlab
}
x =
{
[1,1] =
1 4 7 10
[1,2] = Matlab
}
===== Macierz komórkowa z napisami =====
* w obiekcie typu cell mozna przechowywać napisy o różnej długości
* jest to wygodny sposób przechowywania zbioru napisow (np. kolejnych linii tekstu)
tekst = {'Ala ma kota', 'Siała baba mak', 'Matlab'}
tekst =
{
[1,1] = Ala ma kota
[1,2] = Siała baba mak
[1,3] = Matlab
}
===== Przydatne funkcje =====
* ''%%cellstr()%%'' zamiana tablicy znakowej na znakową macierz komórkową. Wypełniające blanki zostają usunięte.
* ''%%char()%%'' zamiana macierzy komórkowej na znakową
* ''%%iscellstr()%%'' sprawdza, czy macierz jest macierzą komórkową z napisami
x = char('Ala', 'Ewa', 'Zenon')
% utowrzenie macierzy komorkowej znakowej (3 napisy)
y = cellstr(x)
whos x y
x =
Ala
Ewa
Zenon
y =
{
[1,1] = Ala
[2,1] = Ewa
[3,1] = Zenon
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
x 3x5 15 char
y 3x1 11 cell
Total is 18 elements using 26 bytes
disp(y{1}) % napis 'Ala'
a = length(y{1})
disp(x(1, :)) % napis 'Ala ' (2 spacje na koncu)
b = length(x(1, :))
Ala
a = 3
Ala
b = 5
tekst = {'Ala', 'Ewa', 'Zenon'};
% utworzenie macierzy znakowaej 3x5
x = char(tekst)
whos x
x =
Ala
Ewa
Zenon
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
x 3x5 15 char
Total is 15 elements using 15 bytes
tekst = {'raz', 'dwa', 'trzy', 'cztery'};
s = char(tekst);
whos tekst s
% czy macierz komórkowa znakowa ?
a = iscellstr(tekst)
b = iscellstr(s)
c = iscellstr({1 , 'A', 'Ala'})
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
tekst 1x4 16 cell
s 4x6 24 char
Total is 28 elements using 40 bytes
a = 1
b = 0
c = 0
**Ćwiczenie**: utwórz tablicę komórkową zawierająca listę imion (np. Ala, Ewa, Janek), drugą zawierająca listę czasowników (np. lubi, je, czyta) i trzecia zawierającą rzeczowniki (np. kamienie, kotlety, koty). Napisz wyrażenie (lub funkcję), które tworzy zdania losując po jednym wyrazie z każdego zbioru (np. Ala lubi koty)
===== Struktury =====
* struktyry posiadają nazwane **pola**, w których mozemy przechowywać zmienne dowolnego typu
* ''%%struktura.pole%%'' dostęp do pól struktury uzyskujemy za pomocą kropki
* możemy je tworzyć przypisując bezpośrednio wartość do pola
* funkcja ''%%struct()%%'' pozwala tworzyć struktury. Argumentami funkcji są kolejne pary określające nazwę pola i wartość\\
''%%struct(nazwa1, wartosc1, nazwa2, wartość2, ...)%%''
# utowrzenie struktury za pomoca przypisania wartości
s1.liczba = 42
s1.nazwa = 'Matlab'
s1.macierz = rand([2,3])
s1 =
scalar structure containing the fields:
liczba = 42
s1 =
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
s1 =
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
macierz =
0.90546 0.84410 0.50294
0.29388 0.36011 0.69174
# utowrzenie struktury za pomoca funkcji struct()
s2 = struct('liczba', 42, 'nazwa', 'Matlab', 'macierz', rand([2,3]))
whos s1 s2 % ta struktura jest macierza 1x1
s2 =
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
macierz =
0.241836 0.230792 0.186499
0.099092 0.119201 0.122511
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
s1 1x1 62 struct
s2 1x1 62 struct
Total is 2 elements using 124 bytes
===== Przydatne funkcje =====
* ''%%rmfield(s, n)%%'' usuwa ze sruktury ''%%s%%'' pole o nazwie ''%%n%%''
* ''%%isstruct(s)%%'' spradza, czy ''%%s%%'' jest strukturą
* ''%%isfield(s, n)%%'' sprawdza, czy pole o nazwie ''%%n%%'' znajduje się w strukturze ''%%s%%''
* ''%%fieldnames(s)%%'' zwraca listę (cell array) nazw pól
s = struct('liczba', 42, 'nazwa', 'Matlab', 'macierz', rand(5));
disp(s)
% nazwy pól struktury
nazwy = fieldnames(s)
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
macierz =
0.038913 0.317290 0.831178 0.354825 0.522132
0.736033 0.781280 0.281603 0.907320 0.272378
0.244622 0.653326 0.608465 0.268054 0.593301
0.818070 0.741613 0.449265 0.981028 0.870832
0.224464 0.475633 0.370601 0.401830 0.257715
nazwy =
{
[1,1] = liczba
[2,1] = nazwa
[3,1] = macierz
}
% nie modyfikuje struktury ale zwraca kopię
rmfield(s, 'macierz')
% aktualna zawartość struktury
disp(s)
ans =
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
macierz =
0.038913 0.317290 0.831178 0.354825 0.522132
0.736033 0.781280 0.281603 0.907320 0.272378
0.244622 0.653326 0.608465 0.268054 0.593301
0.818070 0.741613 0.449265 0.981028 0.870832
0.224464 0.475633 0.370601 0.401830 0.257715
% podstawiamy wynik aby zachować zmiany
s = rmfield(s, 'macierz')
disp(s)
s =
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
scalar structure containing the fields:
liczba = 42
nazwa = Matlab
% czy struktura zawiera pole o danej nazwie?
a = isfield(s, 'liczba')
b = isfield(s, 'xxx')
a = 1
b = 0
Do pól struktury możemy odnosić się również używając nazw pól w postaci łańcuchów znakowych
s = struct('liczba', 42, 'nazwa', 'Matlab', 'macierz', rand(5));
% pole o nazwie 'liczba'
a = s.('liczba')
t = 'nazwa'
% nazwa pola zawarta w zmiennej
b = s.(t)
n = fieldnames(s);
for i=1:length(n)
fprintf('\nPole o nazwie %s\n', n{i})
disp(s.(n{i}))
end
a = 42
t = nazwa
b = Matlab
Pole o nazwie liczba
42
Pole o nazwie nazwa
Matlab
Pole o nazwie macierz
0.912414 0.920362 0.263780 0.128573 0.340286
0.663009 0.914018 0.881667 0.286782 0.813027
0.648888 0.489993 0.766774 0.403041 0.284646
0.651711 0.414582 0.074597 0.489842 0.120202
0.136358 0.300551 0.394563 0.728933 0.287581
===== Wektory i macierze struktur =====
* struktury moga byc elementami wektorów i macierzy (struct array)
* tworzymy je odnosząc się do indeksów macierzy (tworzenie dynamiczne)
* funkcja ''%%repmat%%'' pozwala utowrzyć macierz z kopiami struktury
sm(1).pole = 5
sm(2).pole = 42
whos sm
sm =
scalar structure containing the fields:
pole = 5
sm =
1x2 struct array containing the fields:
pole
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
sm 1x2 16 struct
Total is 2 elements using 16 bytes
# prealokacja macierzy strukrur przez zdefiniowanie ostatniego elementu
sa(10).pole = 3
whos sa
disp(sa)
sa =
1x10 struct array containing the fields:
pole
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
sa 1x10 8 struct
Total is 10 elements using 8 bytes
1x10 struct array containing the fields:
pole
% macierz 10x10 pustych elementów (tylko sb(10,10) jest strukturą z wartością pola 5 )
sb(10,10).pole = 5
whos sb
disp(sb)
sb(1,1)
sb(10,10)
sb =
10x10 struct array containing the fields:
pole
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
sb 10x10 8 struct
Total is 100 elements using 8 bytes
10x10 struct array containing the fields:
pole
ans =
scalar structure containing the fields:
pole = [](0x0)
ans =
scalar structure containing the fields:
pole = 5
% alokacja macierzy struktur za pomocą funkcji repmat
s3 = repmat(struct('pole', 42, 'nazwa', 'Matlab'), 2, 3)
whos s3
disp(s3)
a = s3(1, 2).pole
s3.pole
whos a
s3 =
2x3 struct array containing the fields:
pole
nazwa
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
s3 2x3 84 struct
Total is 6 elements using 84 bytes
2x3 struct array containing the fields:
pole
nazwa
a = 42
ans = 42
ans = 42
ans = 42
ans = 42
ans = 42
ans = 42
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x1 8 double
Total is 1 element using 8 bytes
Elementy pól wybranych struktur mogą być uzyte do utworzenia macierzy z tymi elementami
% umieszczenie wartości pól struktury w wektorze
a = [ s3.pole ]
whos a
size(a)
a =
42 42 42 42 42 42
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
a 1x6 48 double
Total is 6 elements using 48 bytes
ans =
1 6
===== Zagnieżdzone struktury =====
* polami struktur moga być dowolne zmienne, w tym inne struktury
st = struct('pole1', struct('a', 13, 'b', 14), 'pole2', struct('x', -1))
disp(st)
% pole 1 jest strukturą
a = st.pole1
% struktura w polu1 ma pole 'a'
b = st.pole1.a
st =
scalar structure containing the fields:
pole1 =
scalar structure containing the fields:
a = 13
b = 14
pole2 =
scalar structure containing the fields:
x = -1
scalar structure containing the fields:
pole1 =
scalar structure containing the fields:
a = 13
b = 14
pole2 =
scalar structure containing the fields:
x = -1
a =
scalar structure containing the fields:
a = 13
b = 14
b = 13
**Ćwiczenie** zaprojektuj i utwórz strukturę, która będzie przechowywała dane dotyczące studenta, takie jak: imię, nazwisko, data urodzenia (data jest też strukturą zawierającą pola: dzień, miesiąc, rok), miejsce zamieszkania (adres zawiera pola: ulica, numer domu, kod pocztowy, kraj). Wprowadź przykładowe dane do struktury.
Utwórz macierz 100x100 zawierającą kopie tej struktury w każdym elemencie.
===== Zamiana struktury na macierz komórkową =====
* ''%%cell2struct()%%'' zamiana macierzy komórkowej na strukturę
* ''%%struct2cell()%%'' zamiana struktury na macierz komórkową
c = {'A', 1, 'Ala', [12,3]};
% utworzenie struktury z nazwami pól 'a', 'b', 'c', 'd'
d = cell2struct(c, {'a', 'b', 'c', 'd'}, 2)
disp(d)
whos c d
d =
scalar structure containing the fields:
a = A
b = 1
c = Ala
d =
12 3
scalar structure containing the fields:
a = A
b = 1
c = Ala
d =
12 3
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
c 1x4 28 cell
d 1x1 28 struct
Total is 5 elements using 56 bytes
% utworzenie macierzy komórkowej ze struktury
e = struct2cell(d)
disp(e)
whos e
e =
{
[1,1] = A
[2,1] = 1
[3,1] = Ala
[4,1] =
12 3
}
{
[1,1] = A
[2,1] = 1
[3,1] = Ala
[4,1] =
12 3
}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
e 4x1 28 cell
Total is 4 elements using 28 bytes
===== Zadanie 8. Licz znaki =====
Stwórz plik o nazwie ''%%licz_znaki.m%%'' a w nim zdefiniuj funkcję o nazwe ''%%licz_znaki()%%'', która dla podanego w argumencie napisu zwraca strukturę zawierającą nastepujące pola:
* ''%%znaki%%'' zawiera ilość znaków w napisie
* ''%%litery%%'' zawiera ilość liter (małych i duzych) w napisie
* ''%%wyrazy%%'' zawiera ilość wyrazów w napisie (wyrazem jest dowolny ciąg znaków oddzielonych przynajmniej jedną spacją)
Argumentem funkcji może być napis lub tablica komórkowa z napisami. Jeżeli argumentem jest pojedynczy napis to wynikiem jest pojedyncza struktura. Jeżeli argumentem jest tablica komórkowa znakowa to wynikiem jest macierz struktur o takim samym wymiarze jak tablica komórkowa dana w argumencie. Każdy element macierzy wynikowej zlicza wówczas znaki odpowiadającego elementowi macierzy komórkowej (zobacz przykład niżej) W przypadku, gdy funkcja zostanie uruchomiona z argumentami innego typu lub w przypadku gdy uzytkonik poda niepoprawną ilość argumentów (różną od 1) to wypisywany jest stosowny komunikat błedu i program się kończy.
**Przykład**
Uruchomienie funkcji
x = licz_znaki('Ala ma kota')
zwróci strukturę zawierającą wartości:
x.znaki = 11
x.litery = 9
x.wyrazy = 3
Gdy argumentem będzie macierz komórkowa z napisami to wynikiem bedzie macierz struktur, np.:
a = { 'Ala ma kota', 'Matlab'};
x = licz_znaki(a)
utowrzy zmienną ''%%x%%'', która jest macierzą 1x2
x(1,1).znaki = 11
x(1,1).litery = 9
x(1,1).wyrazy = 3
x(1,2).znaki = 6
x(1,2).litery = 6
x(1,2).wyrazy = 1