структуры в Matlab - PullRequest
       9

структуры в Matlab

2 голосов
/ 12 февраля 2012

% пример

clear all
a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));

Представьте, что структуры представляют временной ряд, где a1 представляет первые 5 дней (например), a2 представляет 5-10 день и так далее ... Я пытаюсьобъединить каждое имя поля в структурах так, чтобы у меня был один непрерывный ряд (вместо того, чтобы разделить их на разные структуры. Например ...

data1 = [a1.data1; a2.data1; a3.data1;a4.data1];

и затем сделайте то же самое для data2 и data3

Каков наилучший способ сделать это?

Ответы [ 2 ]

7 голосов
/ 12 февраля 2012

Лучший способ - заранее определить структуры как массив структур:

a(1) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(2) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(3) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
a(4) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));

, что позволяет довольно легко получить данные:

cat(1,a.data1)

Но если вы настаиваетеиспользуя N структур, затем попробуйте это:

function so3
    a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
    a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
    a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
    a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));

    s{1} = struct2cell(a1);
    s{2} = struct2cell(a2);
    s{3} = struct2cell(a3);
    s{4} = struct2cell(a4);

    N = numel(fieldnames(a1));
    data = cell([1 N]);
    for i=1:N
        data{i} = cell2mat(cellfun(@(x){x{i}'},s));
    end

end
2 голосов
/ 12 февраля 2012

@ Андрей прав, говоря, что «лучший способ - заранее определить структуры как массив структур». Его ответ завершен. Но я не могу не дать следующий более компактный код для случая, когда «настаивают на использовании N структур». Предполагается, что их имена начинаются с foo и заканчиваются числом, например. foo1, foo2, foo21, и это приведет к тому, что поля данных будут расположены в алфавитном порядке по отношению к именам foo.

% first make some data
foo1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));
foo4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3));

Теперь мы получаем список переменных в рабочей области, которые начинаются с foo и заканчиваются некоторым числом, и помещаем их в ячейку, а затем вычисляем конкатенацию этой ячейки через запятую, устанавливая foo в качестве этого значения.

varstarter = 'foo';
varlist = who('-regexp', ['^' varstarter '[0-9]+']);
try
    eval([varstarter '=[' sprintf('%s,',varlist{:}) '];']);
catch
    warning('Could not concatenate variables starting with "%s".',varstarter); 
end

Это позволяет нам напрямую использовать @ Андрей ответ:

data1 = cat(1, foo.data1);
data2 = cat(1, foo.data2);
data3 = cat(1, foo.data3);

Редактировать (приложение): Вы можете еще немного автоматизировать этот последний шаг, просматривая имена полей foo и назначая переменные с тем же именем для конкатенации. Если вы хотите разные имена, код не сложно изменить. Также, возможно, добавьте проверку, чтобы убедиться, что вещь действительно имеет поля.

if ~isstruct(foo)
    warning('Variable "%s" is of an unexpected type.',varstarter);
else
    varfields = fieldnames(foo);
    for k=1:length(varfields)
        eval([varfields{k} '=cat(1, ' varstarter '.' varfields{k} ');']);
    end
end

В духе избегания явных циклов, потому что это забавно, вот эквивалентный код для бита внутри оператора else:

varfields = repmat(fieldnames(foo)',2,1);
eval(sprintf(['%s=cat(1,' varstarter '.%s);'],varfields{:}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...