Как инициализировать массив структур Matlab для роста? - PullRequest
0 голосов
/ 26 августа 2018

Увеличение массива, например через x = [x, a] в цикле, как правило, не одобряется в программировании Matlab, потому что это приводит к одной или нескольким операциям изменения размера, и, следовательно, предварительное распределение обычно является лучшим вариантом. Однако в некоторых контекстах, например, как сокращение сокращения в parfor блоке, оно может иметь преимущества. Для этого массив должен быть создан как нулевой размер. Для числовых массивов выражение для этого равно [], для массивов ячеек {}.

Для структурных массивов это не так ясно. Например, при инициализации struct() создается не структурный массив нулевого размера, а структурный массив 1x1 без полей. Это приводит к ошибке

Ошибка при использовании horzcat
Количество полей в объединяемых структурных массивах не совпадают.
Конкатенация структурных массивов требует, чтобы эти массивы имели одинаковый набор полей.

при росте, поскольку структура полей добавленных структур несовместима со структурой «без полей».

Как инициализировать структурный массив нулевого размера для роста?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Рост массива путем конкатенации

x = [x, 0];

очень медленный, см. здесь и здесь .Вместо этого следует (если предварительное выделение невозможно по какой-либо причине) увеличить массив, добавив новый элемент, например, так:

x(end+1) = 0;

Причина в том, что [x,0] создает новый массив, копируястарые данные в него, на каждой итерации одного цикла, тогда как другая форма расширяет массив, требуя перераспределения только изредка (удваивает основной объем памяти, когда массив становится слишком маленьким).

Инициализация пустой структурымассив (как предложенный @LuisMendo в комментарии ) можно сделать так:

s = struct('field1', {}, 'field2', {});

Чтобы добавить к нему, выполните:

s(end+1) = struct('field1', 1, 'field2', 'x');

В качестве альтернативы, одинможно добавить с помощью

s(end+1).field1 = 5;
s(end).field2 = 'y';

Обратите внимание, что в этом случае end+1 происходит только при первом добавлении нового элемента в массив, последующие поля записываются в последний элемент массива.

0 голосов
/ 26 августа 2018

Получается, что ответом является инициализация числового массива нулевого размера, x = []. Даже если это не структурный массив, добавление структуры a через x = [x, a] создает структурный массив 1x1, к которому можно добавить дополнительные структуры с теми же полями.

Такое неинтуитивное поведение, кажется, является общим причудами языка Matlab, в том смысле, что [] имеет «гибкий тип». Изначально это массив двойных нулей, но добавление одиночных символов делает его единым массивом, а добавление массивов ячеек делает его массивом ячеек.

Как отметил @LuisMendo в комментариях, struct([]) напрямую дает структурный массив нулевого размера без полей. Этот синтаксис может быть предпочтительным, потому что он менее неоднозначен. Кроме того, s = struct('field1', {}, 'field2', {}) может использоваться для создания структурного массива нулевого размера с определенными полями.


Я только что обнаружил, что предложение @ CrisLuengo в комментариях, добавляемое по присваиванию к end + 1 вместо конкатенации, не работает в контексте вопроса "инициализировать для роста". Присвоение не может изменить «тип» структуры, который определяется ее полями. Переход от полей без полей к полям любой структуры, которая должна быть добавлена, приводит к ошибке «Назначение по подписке между разнородными структурами». (но см. его комментарий и мой ответ для разъяснения)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...