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.poledostę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 srukturyspole o nazwienisstruct(s)spradza, czysjest strukturąisfield(s, n)sprawdza, czy pole o nazwienznajduje się w strukturzesfieldnames(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
repmatpozwala 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:
znakizawiera ilość znaków w napisieliteryzawiera ilość liter (małych i duzych) w napisiewyrazyzawiera 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