【问题标题】:Find Values in cell array of struct在结构的单元格数组中查找值
【发布时间】:2013-04-09 14:20:30
【问题描述】:

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

示例:

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"

并且在结构“Attributes”中的xmlFB中有两个字段“Name”和“Typ

名称是独一无二的。

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

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

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

【问题讨论】:

  • 请在名称和类型字段中准确指定值的类别和大小。
  • 我不确定我是否理解你的意思。但它们都是char和max。是 20 个字符。
  • 谢谢,这正是我们所需要的。我基本上要求输出classsize 函数。只是为了确保我的假设是正确的。

标签: matlab struct cell


【解决方案1】:

假设 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 语句中。

【讨论】:

  • @RodyOldenhuis 你离开太久了,Rody :)
【解决方案2】:

使用循环。

首先要做的事:只有在真正出现问题时才开始担心性能,并且只有在之后你才能解决问题。

现在,如果我理解正确的话,这里通常有两种方法可以完成你想要的:

% 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 中不使用循环的建议已经完全过时了;请忽略它:)

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 2020-09-06
    • 1970-01-01
    相关资源
    最近更新 更多