Векторизация многоуровневой индексации структур в MATLAB

Скажем, у меня есть следующее в MATLAB:

a(1).b.c = 4;
a(2).b.c = 5;
a(3).b.c = 7;
....

Я хотел бы собирать значения [4 5 7 ...] в одном массиве без циклов и в векторном виде.

Я пробовал:

>> a(:).b.c 
# Error: Scalar index required for this type of multi-level indexing.

и

>> a.b.c
# Error: Dot name reference on non-scalar structure.

но они не сработали. Лучшее, что я мог придумать, было:

arrayfun(@(x) x.b.c, a);

но насколько я понимаю arrayfun не векторизован, или это?

Ответы

Ответ 1

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

y = subsref([a.b], substruct('.', c));

Обратите внимание, что a.b.c фактически совпадает с:

y = subsref(a.b, substruct('.', c))

Вот почему он не должен работать для нескалярного a.

Ответ 2

Ваш вызов arrayfun кажется мне настолько идиоматичным для меня в Matlab. Я не думаю, что это векторизованное, но оно хорошо оптимизировано и, возможно, самый быстрый способ. Вы также должны попытаться сравнить с циклом, чтобы увидеть, хорошо ли работает JIT-компилятор. Трудно знать без тестирования.

Ответ 3

Вы можете сделать это в двух строках:

>> s = [a.b];
>> y = [s.c]
y =
     4     5     7

Другой возможный однострочный (менее читаемый!):

>> y = squeeze(cell2mat( struct2cell([a.b]) ))
y =
     4
     5
     7