2

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

例子:

xmlFB =
第 1 至 5 列
[1x1 结构] [1x1 结构] [1x1 结构] [1x1 结构] [1x1 结构]

xml链接 = 第 1 至 3 列 [1x1 结构] [1x1 结构] [1x1 结构]

xmlFB{1} 答案=

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

在“ xmllink ”中有结构“ Attributes ”,其中有字段“ Name ”,值为“ EN1

并且在结构“属性”中的xmlFB中有两个字段“名称”和“类型”

名称是独一无二的。

我想做的是从“ xmllink ”中的名称中找到“ xmlFB ”中的“ Typ ”。

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

有没有办法用这些来做到这一点?还是循环更好?

4

2 回答 2

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匹配结构。

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

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

于 2013-04-09T14:37:10.203 回答
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 中不使用循环的建议已经完全过时了。请忽略它:)

于 2013-04-09T15:01:32.983 回答