Подтвердить что ты не робот

Как инициализировать массив структур в MATLAB?

Как я могу предварительно выделить массив структур в MATLAB? Я хочу предварительно выделить "a" в этом примере, чтобы он не изменялся несколько раз.

a = []
for i = 1:100
  a(i).x = i;
end
4b9b3361

Ответ 1

Использование repmat на сегодняшний день является наиболее эффективным способом предварительного выделения структур:

N = 10000;    
b = repmat(struct('x',1), N, 1 );

Это в ~ 10 раз быстрее с использованием Matlab 2011a, чем при предварительном распределении с помощью индексации, как в

N      = 10000;
b(N).x = 1

Метод индексации лишь незначительно быстрее, чем предварительное выделение.

No preallocation:            0.075524    
Preallocate Using indexing:  0.063774
Preallocate with repmat:     0.005234


Код ниже на случай, если вы хотите проверить.

        clear;
        N = 10000;

    %1) GROWING A STRUCT
        tic;
        for ii=1:N
            a(ii).x(1)=1;    
        end
        noPreAll = toc;        

    %2)PREALLOCATING A STRUCT
        tic;
        b = repmat( struct( 'x', 1 ), N, 1 );
        for ii=1:N
            b(ii).x(1)=1;    
        end;  
        repmatBased=toc;        

    %3)Index to preallocate
        tic;
        c(N).x = 1;
        for ii=1:N
            c(ii).x(1)=1;    
        end;  
        preIndex=toc;

        disp(['No preallocation:        ' num2str(noPreAll)])            
        disp(['Preallocate Indexing:    ' num2str(preIndex)])
        disp(['Preallocate with repmat: ' num2str(repmatBased)])

Результаты в командном окне:

No preallocation:        0.075524    
Preallocate Indexing:    0.063774
Preallocate with repmat: 0.0052338
>> 

PS Мне было бы интересно узнать, почему это так, если кто-нибудь может это объяснить.

Ответ 2

Здесь приятно обсудить это в блоге Loren on the Art of MATLAB.

Если вы правильно поняли, вот способы инициализации структуры, которую вы хотите:

a(100).x = 100;

С помощью этого метода мы можем видеть, что элементы заполняются пустыми массивами.

Ответ 3

Существует несколько способов инициализации структуры. Например, вы можете использовать команду struct:

a(1:100) = struct('x',[]);

который устанавливает все поля x в пустые.

Вы также можете использовать deal для создания и заполнения структуры, если вы знаете, какие данные должны туда идти

xx = num2cell(1:100);
[a(1:100).x]=deal(xx{:});
a(99).x
ans =
    99

Или вы можете снова использовать struct (обратите внимание, что если поле структуры должно быть массивом ячеек, ячейка должна быть заключена в фигурные скобки!)

a = struct('x',xx)

Ответ 4

То, как это должно быть сделано, и самое простое

a=struct('x',cell(1,N));

Если вы исправите отсутствующий "тик" и добавите этот метод в код тестирования, представленный jerad, предложенный выше метод будет немного медленнее, чем repmat, но намного проще в реализации, вот результат:

No preallocation:        0.10137
Preallocate Indexing:    0.07615
Preallocate with repmat: 0.01458
Preallocate with struct: 0.07588

Причина, по которой repmat выполняется быстрее, заключается в том, что значение для каждого поля 'x' присваивается во время предварительного выделения, а не остается пустым. Если вышеописанный метод предварительного выделения изменяется, поэтому мы начинаем со всех полей x с назначенным значением (один), например так:

    a=cell(1,N);
    a(:)={1};
    d=struct('x',a);

Затем бенчмаркинг значительно улучшился, был очень близок или немного быстрее, чем repmat. Разница настолько мала, что каждый раз, когда я запускаю ее, она меняет, какая из них быстрее. Вот пример вывода:

No preallocation:        0.0962
Preallocate Indexing:    0.0745
Preallocate with repmat: 0.0259
Preallocate with struct: 0.0184

И наоборот, если предварительное распределение repmat изменяется, чтобы установить поле пустым, как это

b = repmat( struct( 'x', {} ), N, 1 );

Все преимущество в скорости потеряно

Ответ 5

В соответствии с этим ответом, есть и другой способ:

[a.x] = deal(val);

где val - это значение, которое вы хотите назначить каждому элементу структуры.

Эффект этой команды отличается от эффекта других, поскольку каждому полю x каждой структуры a присваивается значение val.

Ответ 6

Вместо предварительного выделения массива структур может быть проще отменить цикл. Таким образом, массив выделяется в первой итерации, а остальные итерации используются для заполнения структур.

a = []
for i = 100:-1:1
    a(i).x = i;
end