【问题标题】:find string in non-scalar structure matlab在非标量结构matlab中查找字符串
【发布时间】:2017-08-25 16:30:38
【问题描述】:

这是 matlab 中的non-scalar structure

clearvars s
s=struct;
for id=1:3
s(id).wa='nko';
s(id).test='5';
s(id).ad(1,1).treasurehunt='asdf'
s(id).ad(1,2).treasurehunt='as df'
s(id).ad(1,3).treasurehunt='foobar'
s(id).ad(2,1).treasurehunt='trea'
s(id).ad(2,2).treasurehunt='foo bar'
s(id).ad(2,3).treasurehunt='treasure'
s(id).ad(id,4).a=magic(5);
end

有没有一种简单的方法来测试结构s 是否包含字符串'treasure',而不必遍历每个字段(例如,通过变量的实际内容执行'grep')?

目的是“快速而肮脏地”查看结构中是否存在字符串(无论在哪里)。换句话说(对于 Linux 用户):我想使用 'grep ' 在 matlab 变量上。

我试过arrayfun(@(x) any(strcmp(x, 'treasure')), s)没有成功,输出:

ans =

  1×3 logical array

   0   0   0

【问题讨论】:

    标签: matlab matlab-struct


    【解决方案1】:

    一种通用方法(适用于任何结构体数组s)是使用struct2cell 将结构体数组转换为元胞数组,测试任何元胞are equal 的内容是否为字符串'treasure',并对包含结构的任何单元格递归地重复上述操作。这可以在while loop 中完成,如果找到字符串或没有剩余的结构可以递归,则停止。这是作为函数实现的解决方案:

    function found = string_hunt(s, str)
      c = reshape(struct2cell(s), [], 1);
      found = any(cellfun(@(v) isequal(v, str), c));
      index = cellfun(@isstruct, c);
      while ~found && any(index)
        c = cellfun(@(v) {reshape(struct2cell(v), [], 1)}, c(index));
        c = vertcat(c{:});
        found = any(cellfun(@(c) isequal(c, str), c));
        index = cellfun(@isstruct, c);
      end
    end
    

    并使用您的示例结构s

    >> string_hunt(s, 'treasure')
    
    ans =
    
      logical
    
       1        % True!
    

    【讨论】:

    • 我更多的是考虑将结构类型转换为字符串,然后搜索它。你能想出一个基于这种方法的简单解决方案吗?基本上我想在 matlab 变量上使用“grep”。
    • @user2305193:没有简单的方法可以将struct 类型转换为另一种类型,因为它实际上是一个容器类而不是数据类型。任何转换都必须在整个深度中递归,而上述解决方案一旦在给定深度找到匹配项就会停止递归,因此它应该非常有效。
    【解决方案2】:

    这是避免显式循环的一种方法

    % Collect all the treasurehunt entries into a cell with strings
    s_cell={s(1).ad.treasurehunt, s(2).ad.treasurehunt, s(3).ad.treasurehunt};
    % Check if any 'treasure 'entries exist
    find_treasure=nonzeros(strcmp('treasure', s_cell));
    % Empty if none
    if isempty(find_treasure)
        disp('Nothing found')
    else
        disp(['Found treasure ',num2str(length(find_treasure)), ' times'])
    end
    

    注意,你也可以这样做

    % Collect all the treasurehunt entries into a cell with strings
    s_cell={s(1).ad.treasurehunt, s(2).ad.treasurehunt, s(3).ad.treasurehunt};
    % Check if any 'treasure 'entries exist
    find_treasure=~isempty(nonzeros(strcmp('treasure', s_cell)));
    

    ..如果您对出现次数不感兴趣

    【讨论】:

      【解决方案3】:

      取决于您的真实数据的格式,以及是否可以找到包含您的字符串的字符串:

      any( ~cellfun('isempty',strfind( arrayfun( @(x)[x.ad.treasurehunt],s,'uni',0 ) ,str)) )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-14
        • 2017-10-07
        • 2020-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多