在struct的单元格数组中查找值

时间:2013-04-09 14:20:31

标签: matlab struct cell

我有两个带有结构的单元格数组。

示例:

xmlFB = 
Columns 1 through 5
[1x1 struct]    [1x1 struct]    [1x1 struct]    [1x1 struct]    [1x1 struct]

xmllink = Columns 1 through 3 [1x1 struct] [1x1 struct] [1x1 struct]

xmlFB{1} ans =

Param: {[1x1 struct] [1x1 struct]} InterChartConnection: [1x1 struct] Tasks: [1x1 struct] Attributes: [1x1 struct] xmllink{1} ans = Attributes: [1x1 struct]

在“ xmllink ”中有结构“属性”,并且字段“名称”的值为“ EN1

在结构“属性”的xmlFB中,有两个字段“名称”和“ Typ

名称是唯一的。

我想要做的是从“ xmllink ”中的名称中找到“ xmlFB ”中的“ Typ ”。< / p>

首先我想做一个Loop,但是我从Matlab读到了这些arrayfun / structfun / cellfun函数。

有没有办法用这些做到这一点?或者更好的循环?

2 个答案:

答案 0 :(得分:3)

假设Names和Typ中的所有变量都是字符串。 (也应该适用于标量。)

以下是如何将值放入单元格数组并链接它们。

% create cell arrays
xmllinkname = cellfun(@(x) x.Attributes.Name, xmllink, 'UniformOutput',0);
xmlFBname = cellfun(@(x) x.Attributes.Name, xmlFB, 'UniformOutput',0);
xmlFBtyp = cellfun(@(x) x.Attributes.Typ, xmlFB, 'UniformOutput',0);

% match names
[idx1, idx2] = ismember(xmllinkname,xmlFBname);
idx2(idx2==0)=[]; % in case some names in xmllink absent in xmlFB

% get matched names and typ
xmllinknamematched = xmllinkname(idx1);
xmllinktyp = xmlFBtyp(idx2);

由于第一个单元格数组中的值的顺序与原始单元格结构数组中的值相同,因此您可以使用这些索引idx1idx2来匹配结构。 / p>

xmllinkmatched = xmllink(idx1);
xmlFBmatched = xmlFB(idx2);

当然,您可以避免创建临时数组并将前两个cellfun语句放入ismember语句中。

答案 1 :(得分:1)

使用循环。

首先要做的事情是:只有在实际出现问题时才会开始担心性能问题,只有 之后才能做到正确。

现在,如果我理解正确,通常有两种方法可以达到你想要的效果:

% create some bogus data with the same structure
% ---------------------------

f_xmllink = @(N) struct(...
    'Attributes', struct(...
        'Name', num2str(N))...
);

f_xmlFB = @(N) struct(...
    'Attributes', struct(...
        'Name', num2str(N),...
        'Typ' , num2str(N))...
);

% using numbers as names
xmllink = {
    f_xmllink(190)
    f_xmllink(331) % 2
    f_xmllink(321) % 3
    f_xmllink(239) 
};

xmlFB = {
    f_xmlFB(331) % 1
    f_xmlFB(200)
    f_xmlFB(108)
    f_xmlFB(321) % 4
    f_xmlFB(035)
};


% Example of a no-loop approach
% ---------------------------

tic

s_exp   = @(s, field) [s.(field)];
s_exp_C = @(s, field) {s.(field)};

one = s_exp_C(s_exp( [xmllink{:}], 'Attributes'), 'Name');
two = s_exp_C(s_exp( [xmlFB{:}], 'Attributes'), 'Name');

[i,j] = find(strcmp(repmat(one,numel(two),1), repmat(two,numel(one),1).'));

s_exp_C(s_exp([xmlFB{i}], 'Attributes'), 'Typ')

toc

% Example of a loop approach
% ---------------------------

tic

for ii = 1:numel(xmllink)

    S = [xmlFB{:}];
    S = [S.Attributes];
    S = {S.Name};

    ind = strmatch(xmllink{ii}.Attributes.Name, S);
    if ~isempty(ind)
        xmlFB{ind}.Attributes.Typ
    end

end

toc

输出:

% no-loop 
ans = 
    '331'    '321'  % correct findings

Elapsed time is 0.001103 seconds.   

% loop
ans =
   331      % correct findings
ans =
   321

Elapsed time is 0.000666 seconds. % FASTER!

当然,比较性能并不是一个公平的测试,但我认为每个人都会同意循环版本至少不会比非循环版本

更重要的是,速度并非一切 - 您需要多长时间才能理解无循环解决方案?您可能在一次读取中理解循环解决方案,而无循环解决方案要复杂得多,并且必须进行全面记录和测试等。此外,对无循环解决方案的更改将比实施更改更难实现。循环解决方案。

在Matlab中不使用循环的建议已经过时了;请忽略它:)