Как я могу индексировать массив 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.

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

Ответ 1

На самом деле можно делать то, что вы хотите, но вам нужно использовать функциональную форму оператора индексирования. Когда вы выполняете операцию индексирования с помощью (), вы фактически вызываете функцию subsref. Итак, хотя вы не можете этого сделать:

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

Вы можете сделать это:

value = subsref(magic(5), struct('type', '()', 'subs', {{3, 3}}));

Уродливый, но возможно.;)

В общем, вам просто нужно изменить шаг индексирования на вызов функции, чтобы у вас не было двух наборов круглых скобок, следующих друг за другом. Другой способ сделать это - определить вашу собственную анонимную функцию, чтобы сделать индексированную индексацию. Например:

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

Однако, когда все сказано и сделано, временное решение локальной переменной гораздо читаемо и, безусловно, я бы предложил.

Ответ 2

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

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

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

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

вернет

ans = 16

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

Эти функции и другие функции теперь доступны в надстройке Функциональные программируемые конструкторы, который доступен через MADLAB Add-On Explorer или на Файловый обмен.

Ответ 3

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

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

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

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

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


UPDATE:

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

[email protected](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 не имеет указателей, вам нужно жить с ним.

Ответ 7

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

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

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

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

Ответ 8

Ваше первоначальное обозначение является наиболее кратким способом сделать это:

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

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

Ответ 9

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

BUILTIN (...) совпадает с FEVAL (...), за исключением того, что он будет вызывать оригинальная встроенная версия функции, даже если перегруженная существует (чтобы это работало, вы никогда не должны перегружать 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.