Как я могу индексировать массив MATLAB, возвращаемый функцией, не назначая его сначала локальной переменной?


например, если я хочу прочитать среднее значение из magic(5), Я могу сделать это так:

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

и value == 13. Я хотел бы иметь возможность сделать что-то вроде одного из них:

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

чтобы обойтись без промежуточной переменной. Однако MATLAB жалуется на Unbalanced or unexpected parenthesis or bracket в первой скобке перед 3.

можно ли считывать значения из массива / матрицы без предварительного присвоения его переменной?

9 313

9 ответов:

Это на самом деле и можно делать то, что вы хотите, но вы должны использовать функциональную форму оператора индексирования. При выполнении операции индексирования с помощью (), вы на самом деле делает вызов subsref

там был просто хороший пост в блоге on Лорен об искусстве Matlab пару дней назад с парой камней, которые могли бы помочь. В частности, с помощью вспомогательных функций, таких как:

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

здесь paren() можно использовать как

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

вернутся

ans = 16

Я бы также предположил, что это будет быстрее, чем ответ gnovice, но я не проверял (используйте профилировщик!!!). Это, как говорится, вы также должны включить эти функции определения где-то есть. Я лично сделал их независимыми функциями на своем пути, потому что они очень полезны.

эти и другие функции теперь доступны в Конструкции Функционального Программирования надстройка, которая доступна через Matlab Add-On Explorer или на Обмен.

как вы относитесь к использованию недокументированных функций:

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

или для массивов ячеек:

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

Так же, как магия:)


обновление:

плохие новости, выше Хак больше не работает в R2015b! Это нормально, это была недокументированная функциональность, и мы не можем полагаться на нее как на поддерживаемую функцию :)

для тех, кто задается вопросом, Где найти этот тип вещи, посмотрите в папке fullfile(matlabroot,'bin','registry'). Там есть куча XML файлы там, которые перечисляют все виды вкусностей. Имейте в виду, что вызов некоторых из этих функций напрямую может легко привести к сбою сеанса MATLAB.

по крайней мере, в MATLAB 2013a вы можете использовать getfield как:

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

чтобы получить элемент (1,2)

к сожалению следующий синтаксис magic(5)(3,3) Не поддерживается matlab. вы должны использовать временные промежуточные переменные. вы можете освободить память после использования, например,

tmp = magic(3);
myVar = tmp(3,3);
clear tmp

обратите внимание, что если вы сравниваете время выполнения со стандартным способом (asign результат, а затем доступ к записям), они точно такие же.

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

на мой взгляд, суть в том, что MATLAB не имеет указателей, вы должны жить с ним.

это может быть проще, если вы сделаете новую функцию:

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

и затем использовать его:

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

ваша начальная нотация-самый краткий способ сделать это:

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

Если вы делаете это в цикле, вы можете просто переназначить M каждый раз и игнорировать четкое утверждение.

чтобы дополнить ответ Амро, вы можете использовать feval вместо builtin. Нет никакой разницы, действительно, если вы не пытаетесь перегрузить функцию оператора:

BUILTIN(...) то же самое, что и ФЕВАЛЬ(...) кроме того, что он будет называть оригинальная встроенная версия функции, даже если она перегружена существует (для этого, чтобы работать, вы не должны перегружать ВСТРОЕННЫЙ.)

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

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

вот что интересно feval Кажется, совсем чуть-чуть быстрее, чем builtin (на ~3,5%), по крайней мере, в Matlab 2013b, что странно, учитывая, что feval нужно проверить, если функция перегружена, в отличие от 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.