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 wymiarachNxM
## 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 2×3 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 10×10 * 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órekcellplot()
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 <https://www.octave.org/missing.html> 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 srukturys
pole o nazwien
isstruct(s)
spradza, czys
jest strukturąisfield(s, n)
sprawdza, czy pole o nazwien
znajduje się w strukturzes
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 100×100 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 napisielitery
zawiera ilość liter (małych i duzych) w napisiewyrazy
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ą 1×2
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