Например, если я хочу прочитать среднее значение из 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
Обратите внимание, что если вы сравниваете время выполнения со стандартным способом (присваиваете результат и затем записываете записи), они будут точно такими же.
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 не имеет указателей, вам нужно жить с ним.
Ответ 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.