Jak mogę indeksować tablicę MATLAB zwracaną przez funkcję bez uprzedniego przypisania jej do zmiennej lokalnej?

Na przykład, jeśli chcę odczytać wartość środkową z magic(5), mogę to zrobić tak:

M = magic(5);
value = M(3,3);

Aby uzyskać value == 13. Chciałbym móc zrobić coś takiego:

value = magic(5)(3,3);
value = (magic(5))(3,3);

Aby zrezygnować ze zmiennej pośredniej. Jednak MATLAB narzeka na Unbalanced or unexpected parenthesis or bracket w pierwszym nawiasie przed 3.

Czy jest możliwe odczytanie wartości z tablicy / macierzy bez uprzedniego przypisania jej do zmiennej?

Author: Jonas Heidelberg, 2010-09-02

9 answers

W rzeczywistości jest możliwe, aby robić to, co chcesz, ale musisz użyć formy funkcjonalnej operatora indeksującego. Kiedy wykonujesz operację indeksowania za pomocą (), w rzeczywistości dzwonisz do subsref funkcja. Więc, nawet jeśli nie możesz zrobić tego:

value = magic(5)(3, 3);

You can do this:

value = subsref(magic(5), struct('type', '()', 'subs', {{3, 3}}));
Brzydkie, ale możliwe. ;)

Ogólnie rzecz biorąc, wystarczy zmienić krok indeksowania na wywołanie funkcji, aby nie mieć dwóch zestawów nawiasy bezpośrednio po sobie. Innym sposobem na to byłoby zdefiniowanie własnej funkcji anonimowej do indeksowania subskrybowanego. Na przykład:

subindex = @(A, r, c) A(r, c);     % An anonymous function for 2-D indexing
value = subindex(magic(5), 3, 3);  % Use the function to index the matrix

Jednak, gdy wszystko zostanie powiedziane i zrobione, tymczasowe rozwiązanie zmiennej lokalnej jest dużo bardziej czytelne i zdecydowanie to, co sugerowałbym.

 342
Author: gnovice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 18:46:47

Był właśniedobry post na blogu naLoren o sztuce Matlab kilka dni temu z kilkoma klejnotami, które mogą pomóc. W szczególności za pomocą funkcji pomocniczych, takich jak:

paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};

Gdzie paren() może być używany jak

paren(magic(5), 3, 3);

Zwróci

ans = 16

Domyślam się również, że będzie to szybsze niż odpowiedź gnovica, ale nie sprawdzałem (użyj profilera!!!). Mając to na uwadze, musisz również gdzieś zawrzeć te definicje funkcji. Ja osobiście zrobiłem są niezależne na mojej drodze, ponieważ są bardzo przydatne.

Te i inne funkcje są teraz dostępne w konstrukcjach programowania funkcyjnego dodatku, który jest dostępny za pośrednictwem Eksploratora dodatków MATLAB lub na wymianie plików .

 113
Author: T. Furfaro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-22 11:44:41

Co sądzisz o używaniu nieudokumentowanych funkcji:

>> builtin('_paren', magic(5), 3, 3)               %# M(3,3)
ans =
    13

Lub dla tablic komórkowych:

>> builtin('_brace', num2cell(magic(5)), 3, 3)     %# C{3,3}
ans =
    13

Just like magic:)


Aktualizacja:

Zła wiadomość, powyższy hack nie działa już w R2015b ! W porządku, była to nieudokumentowana funkcjonalność i nie możemy polegać na niej jako obsługiwanej funkcji:)

Dla tych, którzy zastanawiają się, gdzie znaleźć tego typu rzeczy, zajrzyj do folderu fullfile(matlabroot,'bin','registry'). Jest tam kilka plików XML, które zawierają wszystkie rodzaje gadżetów. Be ostrzegł, że wywołanie niektórych z tych funkcji bezpośrednio może łatwo spowodować awarię sesji MATLAB.

 74
Author: Amro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-31 07:54:47

Przynajmniej w MATLAB 2013a można użyć getfield like:

a=rand(5);
getfield(a,{1,2}) % etc

Aby uzyskać element at (1,2)

 48
Author: Ian M. García,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-30 20:25:46

Niestety składnia podobna do magic(5)(3,3) nie jest obsługiwana przez matlab. musisz użyć tymczasowych zmiennych pośrednich. możesz zwolnić pamięć po użyciu, np.

tmp = magic(3);
myVar = tmp(3,3);
clear tmp
 15
Author: second,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-02 12:46:10

Zauważ, że jeśli porównasz czasy uruchomienia ze standardowym sposobem (jako znak wyniku i następnie dostęp do wpisów), są one dokładnie takie same.

subs=@(M,i,j) M(i,j);
>> for nit=1:10;tic;subs(magic(100),1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0103

>> for nit=1:10,tic;M=magic(100); M(1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0101

Moim zdaniem najważniejsze jest to, że MATLAB nie ma wskaźników, trzeba z tym żyć.

 12
Author: titus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 18:31:09

Może być prostsze, jeśli stworzysz nową funkcję:

function [ element ] = getElem( matrix, index1, index2 )
    element = matrix(index1, index2);
end

A następnie użyj go:

value = getElem(magic(5), 3, 3);
 6
Author: Vugar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 16:58:07

Twoja początkowa notacja jest najbardziej zwięzłym sposobem, aby to zrobić:

M = magic(5);  %create
value = M(3,3);  % extract useful data
clear M;  %free memory

Jeśli robisz to w pętli, możesz po prostu zmienić przypisanie M za każdym razem i zignorować jasne oświadczenie.

 4
Author: Andreas GS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-20 18:16:36

Aby uzupełnić odpowiedź Amro, możesz użyć feval zamiast builtin. Nie ma różnicy, naprawdę, chyba że spróbujesz przeciążyć funkcję operatora:

BUILTIN(...) jest tym samym co FEVAL(...) z tym, że będzie to wywoływać oryginalna wbudowana wersja funkcji nawet w przypadku przeciążenia istnieje (aby to działało, nie wolno przeciążać BUILTIN).

>> feval('_paren', magic(5), 3, 3)               % M(3,3)
ans =
    13

>> feval('_brace', num2cell(magic(5)), 3, 3)     % C{3,3}
ans =
    13

Ciekawe jest to, że feval wydaje się być trochę szybszy niż builtin (o ~3,5%), w najmniej w Matlab 2013b, co jest dziwne, biorąc pod uwagę, że feval musi sprawdzić, czy funkcja jest przeciążona, w przeciwieństwie do builtin:

>> tic; for i=1:1e6, feval('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 49.904117 seconds.
>> tic; for i=1:1e6, builtin('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 51.485339 seconds.
 1
Author: nirvana-msu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-12 20:54:00