如何在MATLAB中计算单元数组中特定字符串的起始和结束索引?

3
假设我们有这样的单元数组:
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中高效完成此操作的方法是什么?

3
如果 strings = {'a','b','a','b'};,那么我的输出将是什么? - rayryeng
4个回答

4
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

虽然对于提供的数据来说这种方法很有效,但我很想看到更真实代表性的数据集,以使该函数更加通用。


3

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'

2
假设你的字符串以连续运行的方式填充,并且该运行是您将看到特定唯一字符串的唯一时间,您可以将其与uniqueaccumarray结合使用。首先,使用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{:});

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

2

使用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]

1
哦!第一个和最后一个标志。非常聪明! - rayryeng
2
@rayryeng 最近我一直在审查许多函数的所有可能输入标志(针对MATL)。这件事情必定会带来好处 :-) - Luis Mendo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接