2011-03-17 114 views
1

我需要在一组单元阵列中找到唯一的单元阵列。例如,如果这是我输入:如何在MATLAB中的一组单元阵列中有效地找到独特的单元阵列?

I = {{'a' 'b' 'c' 'd' 'e'} ... 
    {'a' 'b' 'c'} ... 
    {'d' 'e'} ... 
    {'a' 'b' 'c' 'd' 'e'} ... 
    {'a' 'b' 'c' 'd' 'e'} ... 
    {'a' 'c' 'e'}}; 

然后,我想我的输出看起来像这样:

I_unique = {{'a' 'b' 'c' 'd' 'e'} ... 
      {'a' 'b' 'c'} ... 
      {'d' 'e'} ... 
      {'a' 'c' 'e'}}; 

你有任何想法如何做到这一点?输出中元素的顺序无关紧要,但效率确实很高,因为单元阵列可能非常大。

+0

细胞是否在输出此事的顺序?你是否按照它们出现在输入中的顺序需要它们?另外,你是否正在处理*很多细胞进行比较(即速度问题)? – gnovice 2011-03-17 17:22:38

+0

您是否打算让每个单元格包含带单引号的单个字符串或包含单字符字符串的列表?你得到了前者 - 一个字符串“在”里面的加倍引号只是一个转义引用。为了得到后者,用空格拆分字符串文字,如{'a''b''c''d''e'}。 – 2011-03-17 18:00:04

+0

嗨,顺序无关紧要。计算时间很重要,因为输入数据可能很大。对不起,我没有指定此问题 - 一个单元中的元素可能包含多个字符,即{'a1''a2''a3'}。 – user664664 2011-03-17 19:23:39

回答

1

如果你的细胞只含有分类单个字符,那么你可以使用保留只是独特的序列:

 
>> I = {{'a' 'b' 'c' 'd' 'e'} {'a' 'b' 'c'} {'d' 'e'} {'a' 'b' 'c' 'd' 'e'} {'a' 'b' 'c' 'd' 'e'} {'a' 'c' 'e'}}; 
>> I_unique = cellfun(@char, I, 'uniformoutput', 0); 
>> I_unique = cellfun(@transpose, I_unique, 'uniformoutput', 0); 
>> I_unique = unique(I_unique) 

I_unique = 

    'abc' 'abcde' 'ace' 'de' 

然后,您可以再次分裂所产生的细胞成单个字符:

 
>> I_unique = cellfun(@transpose, I_unique, 'uniformoutput', 0); 
>> I_unique = cellfun(@cellstr, I_unique, 'uniformoutput', 0); 
>> I_unique = cellfun(@transpose, I_unique, 'uniformoutput', 0); 
>> I_unique{:} 

ans = 

    'a' 'b' 'c' 


ans = 

    'a' 'b' 'c' 'd' 'e' 


ans = 

    'a' 'c' 'e' 


ans = 

    'd' 'e' 
+0

非常感谢您的回答。 – user664664 2011-03-17 19:05:05

1

编辑:已更新为使用更高效的算法。

如果效率相当于I中的大量集合,那么您的最佳选择可能是推出自己的优化循环。这个问题与前面关于how to efficiently remove sets that are subsets of or equal to another的问题有一些相似之处。这里的区别在于你不关心删除子集,只是重复,所以my answer to the other question中的代码可以修改,以进一步减少进行比较的次数。

首先我们可以认识到,比较具有不同数量元素的集合没有意义,因为它们在这种情况下不可能匹配。因此,第一步是计算每个集合中的字符串数量,然后遍历每个具有相同字符串数量的集合组。

对于这些组中的每个组,我们将有两个嵌套循环:每个集合的外部循环从集合的结尾开始,以及一个内部循环遍布在每个集合的前面。如果/当找到第一个匹配时,我们可以将该集合标记为“不唯一”,并打破内部循环以避免额外的比较。在集合的末尾启动外部循环会给我们额外的奖励,在I_unique中设置的额外奖励将保持I的出现顺序。

这里是生成的代码:

I = {{'a' 'b' 'c' 'd' 'e'} ... %# The sample cell array of cell arrays of 
    {'a' 'b' 'c'} ...   %# strings from the question 
    {'d' 'e'} ... 
    {'a' 'b' 'c' 'd' 'e'} ... 
    {'a' 'b' 'c' 'd' 'e'} ... 
    {'a' 'c' 'e'}}; 
nSets = numel(I);     %# The number of sets 
nStrings = cellfun('prodofsize',I); %# The number of strings per set 
uniqueIndex = true(1,nSets);   %# A logical index of unique elements 

for currentSize = unique(nStrings) %# Loop over each unique number of strings 

    subIndex = find(nStrings == currentSize); %# Get the subset of I with the 
    subSet = I(subIndex);      %# given number of strings 

    for currentIndex = numel(subSet):-1:2  %# Outer loop 
    for compareIndex = 1:currentIndex-1  %# Inner loop 
     if isequal(subSet{currentIndex},subSet{compareIndex}) %# Check equality 
     uniqueIndex(subIndex(currentIndex)) = false; %# Mark as "not unique" 
     break        %# Break the inner loop 
     end 
    end 
    end 

end 

I_unique = I(uniqueIndex); %# Get the unique values 
+0

非常感谢,这正是我需要的。 – user664664 2011-03-17 19:05:50