【问题标题】:Finding string in cell array of cell arrays在元胞数组的元胞数组中查找字符串
【发布时间】:2015-04-23 20:46:12
【问题描述】:

使用 Matlab,假设我们有一个元胞数组。例如:

C = { {'hello' 'there' 'friend'}, {'do' 'say' 'hello'}, {'or' 'maybe' 'not'} }

我想查找 C 中包含字符串 'hello' 的所有元胞数组的索引。在这种情况下,我希望是 1 和 2,因为第一个单元阵列在第一个插槽中有 'hello',而第二个单元阵列在第三个插槽中有它。

我想象使用矩阵(一个简单的查找)会容易得多,但出于教育目的,我也想使用元胞数组的元胞数组来学习这个过程。

非常感谢。

【问题讨论】:

    标签: matlab cell-array


    【解决方案1】:

    直截了当的方法

    arrayfun -

    out = find(arrayfun(@(n) any(strcmp(C{n},'hello')),1:numel(C)))
    

    cellfun -

    out = find(cellfun(@(x) any(strcmp(x,'hello')),C))
    

    替代方法

    您可以采用一种新方法翻译 cell array of cell arrays of strings 的输入为cell array of strings,从而减少一个级别 "cell hierarchy"。然后,它执行strcmp,从而避免cellfunarrayfun,这可能使其比之前列出的方法更快。请注意,如果输入元胞数组的每个元胞中的元胞数量变化不大,这种方法从性能的角度来看会更有意义,因为这种转换会导致 2D 元胞数组中的空元胞被填满 空的地方。

    这是实现 -

    %// Convert cell array of cell ararys to a cell array of strings, i.e.
    %// remove one level of "cell hierarchy"
    lens = cellfun('length',C)
    max_lens = max(lens) 
    C1 = cell(max_lens,numel(C))
    C1(bsxfun(@le,[1:max_lens]',lens)) = [C{:}]  %//'
    
    %// Use strsmp without cellfun and this might speed it up
    out = find(any(strcmp(C1,'hello'),1))
    

    说明:

    [1] 将字符串元胞数组的元胞数组转换为字符串元胞数组:

    C = { {'hello' 'there' 'friend'}, {'do' 'hello'}, {'or' 'maybe' 'not'} }
    

    转换成

    C1 = {
        'hello'     'do'       'or'   
        'there'     'hello'    'maybe'
        'friend'         []    'not'  }
    

    [2] 为每一列查找是否有any 字符串hello 并找到那些列IDs 作为最终输出。

    【讨论】:

    • 不错!我很想发布基于regexp 的解决方案(与昨天相同的场景哈哈),但strcmp 是这里的最佳选择:)
    • @Benoit_11 如果有可供 OP 使用的替代方案,那就太好了! :)
    • 谢谢,我选择了这个解决方案,因为它比使用正则表达式更快。按预期工作!
    • @Manbearpig 添加了另一种方法,看看它是如何在运行时对您的数据执行的!?谢谢。
    【解决方案2】:

    这是一种使用正则表达式的方法,我认为它的效率远低于@Divakar 的strcmp 解决方案,但无论如何这可能会提供信息。

    regexp对元胞数组进行操作,但由于C是元胞数组的元胞数组,我们需要使用cellfun来得到元胞数组的逻辑元胞数组,之后我们再次使用cellfun获取匹配的索引。实际上我可能使用了不必要的步骤,但我认为这样更直观

    代码:

    clear
    clc
    
    C = { {'hello' 'there' 'friend'}, {'do' 'say' 'hello'}, {'or' 'maybe' 'not'} }
    
    CheckWord = cellfun(@(x) regexp(x,'hello'),C,'uni',false);
    

    这里的CheckWord 是一个包含 0 或 1 的元胞数组,具体取决于与字符串 hello 的匹配:

    CheckWord = 
    
        {1x3 cell}    {1x3 cell}    {1x3 cell}
    

    为了让事情更清楚,让我们重塑CheckWord

    CheckWord = reshape([CheckWord{:}],numel(C),[]).'
    
    CheckWord = 
    
        [1]    []     []
         []    []    [1]
         []    []     []
    

    由于CheckWord 是一个单元格数组,我们可以使用cellfunfind 来查找非空单元格,即与匹配项对应的单元格:

    [row col] = find(~cellfun('isempty',CheckWord))
    
    row =
    
         1
         2
    
    col =
    
         1
         3
    

    因此,包含单词“hello”的单元格是第一个和第二个。

    希望有帮助!

    【讨论】:

    • 不客气!这就是这个网站的目的:)
    【解决方案3】:

    假设内部单元格数组是 horizo​​ntalequal-sized(如您的示例所示),并且您希望找到 exact 匹配项字符串:

    result = find(any(strcmp(vertcat(C{:}),'hello'), 2));
    

    它的工作原理如下:

    1. 将字符串元胞数组C 的元胞数组转换为字符串的二维元胞数组:vertcat(C{:})
    2. 将每个字符串与寻找的字符串('hello')进行比较:strcmp(...,'hello')
    3. 查找找到匹配的行的索引:find(any(..., 2))

    【讨论】:

    • 不幸的是,内部单元格数组的大小不会相等。我的意见只是巧合。但无论如何,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多