【问题标题】:How we can calculate starting and ending indices of specific string in a cell array in MATLAB?我们如何在 MATLAB 中计算单元格数组中特定字符串的开始和结束索引?
【发布时间】:2016-02-17 22:45:43
【问题描述】:

假设我们有这个元胞数组:

strings = {'a'; 'a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'b'; 'm'; 'm'; 'm'; 'm'};

我想要这样的输出:

a  1    6
b  7    10
m  11   14

数字显示每个唯一字符串的开始和结束索引。然而,这只是一个例子。我的元胞数组有 100 多个唯一字符串。在 MATLAB 中执行此操作的有效方法是什么?

【问题讨论】:

  • 如果strings = {'a','b','a','b'};,你的输出是什么?

标签: string matlab duplicates unique cell


【解决方案1】:

unique 的输出应该立即为您提供所需的内容:

strings = {'a'; 'a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'b'; 'm'; 'm'; 'm'; 'm'};
[uniquestrings, start, bin] = unique(strings);

地点:

uniquestrings = 

    'a'    'b'    'm'


start =

     1     7    11


bin =

     1     1     1     1     1     1     2     2     2     2     3     3     3     3

虽然这对提供的数据很有效,但我很想看到一个更“真实”的代表性数据集,以使函数更通用。

【讨论】:

    【解决方案2】:

    unique 开始将您的数据映射到索引:

    [~,~,ix]=unique(strings);
    d=[];
    %calculate end indices
    d(:,2)=[find(diff(ix));numel(ix)]
    %calculate start indices
    d(:,1)=[1;d(1:end-1,2)+1]
    %corresponding chars:
    e=strings(d(:,1))
    

    输出是:

    d =
    
         1     6
         7    10
        11    14
    
    
    e = 
    
        'a'
        'b'
        'm'
    

    【讨论】:

      【解决方案3】:

      假设您的字符串是以连续运行字符串的方式填充的,并且该运行是唯一一次您会看到特定的唯一字符串,您可以将其与 unique 结合使用和accumarray。首先,使用unique 获取所有唯一字符串的列表,然后为每个字符串分配一个唯一ID,从1 到您拥有的所有唯一字符串。 unique 的问题是,一旦您对字符串进行排序,就会分配 ID。您不想这样做,因为您想按原样使用字符串的位置来确定它们运行的​​开始和结束位置。因此,您需要使用 'stable' 标志。您需要第一个输出为您提供数组中的唯一字符串(供稍后使用)和第三个输出来获得这个新的 ID 分配:

      strings = {'a'; 'a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'b'; 'm'; 'm'; 'm'; 'm'};
      [s,~,id] = unique(strings, 'stable');
      

      现在你有了这个,使用accumarray 这样你就可以获取每个 ID 并将它们组合在一起。在这种情况下,您需要使用与每个唯一字符串关联的位置编号,并且您需要将属于同一字符 ID 的所有位置编号合并在一起。完成此操作后,我们可以输出一个元素元胞数组,其中每个元素都是一个二元向量,为您提供每次运行的最小和最大位置。

      out = accumarray(id, (1:numel(strings)).', [], @(x) {[min(x), max(x)]});
      

      然后您可以将其显示在一个漂亮的表格中:

      T = table(s, vertcat(out{:}), 'VariableNames', {'Letter', 'BeginEnd'});
      

      我们得到:

      T = 
      
          Letter    BeginEnd
          ______    ________
      
          'a'        1     6
          'b'        7    10
          'm'       11    14
      

      但是,如果您想获取矩阵中的第一个和最后一个元素,只需执行以下操作:

      ind = vertcat(out{:});
      

      第一列给出每个字符的起始位置,第二列给出每个字符的结束位置。

      【讨论】:

        【解决方案4】:

        使用unique的另一种方法:

        strings = {'a'; 'a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'b'; 'm'; 'm'; 'm'; 'm'};
        [u, l] = unique(strings, 'last');
        [~, f] = unique(strings, 'first');
        

        这给了

        u = 
            'a'
            'b'
            'm'
        f =
             1
             7
            11
        l =
             6
            10
            14
        

        或者您可以将结果连接到一个元胞数组中

        result = [u num2cell([f l])]
        

        生产

        result = 
            'a'    [ 1]    [ 6]
            'b'    [ 7]    [10]
            'm'    [11]    [14]
        

        【讨论】:

        • 噢噢噢噢!第一个和最后一个标志。非常聪明!
        • @rayryeng 最近我一直在审查许多函数(对于 MATL)的所有可能的输入标志。好的东西必须来自那里:-)
        猜你喜欢
        • 1970-01-01
        • 2013-06-16
        • 2021-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-06
        • 1970-01-01
        相关资源
        最近更新 更多