消除具有相同元素的细胞阵列

时间:2017-12-03 00:35:58

标签: matlab

在我的主脚本中,我试图消除具有相同元素的S单元格数组。例如,如果您运行当前脚本(使用a=v=2),那么您将获得S的以下值:

S{1}(:, :, 1) = [0 0; 0 0]; S{1}(:, :, 2) = [0 0; 0 0];
S{2}(:, :, 1) = [0 0; 1 1]; S{2}(:, :, 2) = [0 1; 0 1];
S{3}(:, :, 1) = [0 1; 0 1]; S{3}(:, :, 2) = [0 0; 1 1];
S{4}(:, :, 1) = [1 0; 1 0]; S{4}(:, :, 2) = [1 1; 0 0];
S{5}(:, :, 1) = [1 1; 0 0]; S{5}(:, :, 2) = [1 0; 1 0];
S{6}(:, :, 1) = [1 1; 1 1]; S{6}(:, :, 2) = [1 1; 1 1];

代码应将S{2}S{3}S{4}S{5}视为具有相同的子集。因此,我希望得到的结果应该是S{1}S{2}S{4}S{6}

我知道MATLAB有ismemberisequal等函数,但它们似乎不适用于单元格数组......或者我无法使它们正常工作。

是否有一种简洁的方法来处理目前正在编写的单元数组?

主脚本:

clear all
clc

a = 2;
v = 2;

R = dec2base(0:1:v^(v^a)-1, v)-'0';
cnt1 = 0;
cnt2 = 0;

for j=1:v^(v^a)
    % List all degenerates in Psi1 
    V =  FN_Break(a, v, R(j,:));
    if V > 0 % Connector is degenerate
        cnt1 = cnt1 + 1;
        Psi1(cnt1,1) = j-1;
        % Store all "breaks" into cell array S
        S{cnt1} = FN_Break_T(a,v,R(j,:));
    else % Connector is not degenerate
        cnt2 = cnt2 + 1;
        Psi2(cnt2,1) = j-1;
    end
end

功能FN_Break

function [valU] = FN_Beak(a, v, R)

FreeAtomCtr = 0;

for j=0:v^a-1
    for k=1:a
        for l=1:a   
            B =  dec2base(j,v,a);
            atom(l,j+1) = str2num(B(l));
        end
    end
end

for j=1:a % Do this for each atom
    cnt(1:v) = 0;
    for k = 1:v^a  % Do this for each position of each atom
        for l=0:v-1       % Break this down for each value
            if atom(j,k) == l
               cnt(1+l) = cnt(1+l) + 1;
               T(1+l, cnt(1+l),j) = R(k); 
            end
        end
    end
end

for j=1:a
    B = unique(T(:,:,j), 'rows');
    if dot(size(B), [1 0]) < v   % does not depend on this atom
       FreeAtomCtr = FreeAtomCtr + 1;
    end
end

valU = FreeAtomCtr;
end

功能FN_Break_T

function [valU] = FN_Beak_T(a, v, R)

FreeAtomCtr = 0;

for j=0:v^a-1
    for k=1:a
        for l=1:a   
            B =  dec2base(j,v,a);
            atom(l,j+1) = str2num(B(l));
        end
    end
end

for j=1:a % Do this for each atom
    cnt(1:v) = 0;
    for k = 1:v^a  % Do this for each position of each atom
        for l=0:v-1       % Break this down for each value
            if atom(j,k) == l
               cnt(1+l) = cnt(1+l) + 1;
               T(1+l, cnt(1+l),j) = R(k); 
            end
        end
    end
end

for j=1:a
    B = unique(T(:,:,j), 'rows');
    if dot(size(B), [1 0]) < v   % does not depend on this atom
       FreeAtomCtr = FreeAtomCtr + 1;
    end
end

valU = T;
end

1 个答案:

答案 0 :(得分:1)

一种方法可能是对您的组合进行哈希处理,并使用它们来比较单元格内容。您可以使用ismember根据可能的组合(在本例中为4)索引对,然后使用sort结果并使用unique查找每个唯一(已排序)哈希的第一个实例

例如:

S{1}(:, :, 1) = [0 0; 0 0]; S{1}(:, :, 2) = [0 0; 0 0];
S{2}(:, :, 1) = [0 0; 1 1]; S{2}(:, :, 2) = [0 1; 0 1];
S{3}(:, :, 1) = [0 1; 0 1]; S{3}(:, :, 2) = [0 0; 1 1];
S{4}(:, :, 1) = [1 0; 1 0]; S{4}(:, :, 2) = [1 1; 0 0];
S{5}(:, :, 1) = [1 1; 0 0]; S{5}(:, :, 2) = [1 0; 1 0];
S{6}(:, :, 1) = [1 1; 1 1]; S{6}(:, :, 2) = [1 1; 1 1];

combinations = [0 0; 0 1; 1 0; 1 1];
% Assume array in every cell has the same shape
hash = zeros(size(S{1}, 1)*size(S{1}, 3), numel(S));
for ii = 1:numel(S)
    [~, hash(:,ii)] = ismember([S{ii}(:, :)].', combinations, 'rows');
end

hash = sort(hash, 1).';
[~, keepidx] = unique(hash, 'rows');
S = S(keepidx);

给出了期望的S(单元格1,2,4,6)

如果您想要嵌套重复项,可以使用以下命令:

hash = sort(hash, 1).';
[~, keepidx, uniqueidx] = unique(hash, 'rows');
bincounts = accumarray(uniqueidx, 1);  % Count occurrences

for ii = 1:numel(bincounts)
    if bincounts(ii) > 1
        idx = find(uniqueidx == ii);
        S{idx(1)} = S(idx);  % Nest duplicates in first instance of duplicate
    end
end
S = S(keepidx);

这使用unique的第三个输出和accumarray来获取每个唯一组合的出现次数。嵌套重复项,然后像以前一样修剪原始单元格数组。