如何找到包含至少一个向量B的元素的单元格A的向量?

时间:2015-01-26 15:02:37

标签: matlab vector cell cell-array

如何查找包含至少一个向量A元素的B向量?

示例:

A = {[2 5],[8 9 2],[33 77 4],[102 6],[10 66 17 7 8 11],[110 99],[1 4 3],[15 41 88]}

B = [5 77 41 66 7]

Result = {[2 5],[33 77 4],[10 66 17 7 8 11],[15 41 88]}

1 个答案:

答案 0 :(得分:11)

途径

使用arrayfunismember -

Result = A(arrayfun(@(n) any(ismember(B,A{n})),1:numel(A)))

arrayfunbsxfun -

Result = A(arrayfun(@(n) any(any(bsxfun(@eq,B(:),A{n}),2)),1:numel(A)))

arrayfunsetdiff -

Result = A(arrayfun(@(n) numel(setdiff(B,A{n})) < numel(B),1:numel(A)))

arrayfunintersect -

Result = A(arrayfun(@(n) ~isempty(intersect(B,A{n})),1:numel(A)))

也可以在这里使用cellfun,这样基于cellfun的四个基于Result = A(cellfun(@(x) any(ismember(B,x)), A)) Result = A(cellfun(@(x) any(any(bsxfun(@eq,B(:),x),2)),A)) Result = A(cellfun(@(x) numel(setdiff(B,x)) < numel(B),A)) Result = A(cellfun(@(x) ~isempty(intersect(B,x)),A)) 的解决方案最终会像这样 -

bsxfun

采用不同的路线[使用arrayfun的屏蔽功能]

通过将cellfun转换为二维数字数组。因此,这里的想法是拥有一个A数组,其中行数是2D中的最大元素数,列数是A中的单元格数。此数组的每一列都包含A的每个单元格中的元素,而A将填充空格

使用这种方法的解决方案代码看起来像这样 -

NaNs

验证

lens = cellfun('length',A); %// number of elements in each cell of A
mask = bsxfun(@ge,lens,(1:max(lens))'); %//'# mask of valid places in the 2D array
A_arr = NaN(size(mask)); %//initialize 2D array in which A elements are to be put
A_arr(mask) = [A{:}]; %// put the elements from A

%// Find if any element from B is in any element along the row or dim-3       
%// locations in A_arr. Then logically index into A with it for the final
%// cell array output
Result = A(any(any(bsxfun(@eq,A_arr,permute(B,[1 3 2])),1),3));

基准

对于有兴趣了解运行时性能的人来说,这是一个快速的基准测试,具有足够大的数据量 -

>> celldisp(Result)
Result{1} =
     2     5
Result{2} =
    33    77     4
Result{3} =
    10    66    17     7     8    11
Result{4} =
    15    41    88

在我的系统上获得的结果是 -

%// Create inputs
N = 10000; %// datasize
max_num_ele = 100; %// max elements in any cell of A
num_ele = randi(max_num_ele,N,1); %// number of elements in each cell of A
A = arrayfun(@(n) randperm(N,num_ele(n)), 1:N, 'uni', 0); 
B = randperm(N,num_ele(1));

%// Warm up tic/toc.
for k = 1:100000
    tic(); elapsed = toc();
end

%// Start timing all approaches
disp('************************  With arrayfun **************************')
disp('------------------------  With arrayfun + ismember')
tic
Result = A(arrayfun(@(n) any(ismember(B,A{n})),1:numel(A)));
toc, clear Result

disp('------------------------  With arrayfun + bsxfun')
tic
Result = A(arrayfun(@(n) any(any(bsxfun(@eq,B(:),A{n}),2)),1:numel(A)));
toc, clear Result

disp('------------------------  With arrayfun + setdiff')
tic
Result = A(arrayfun(@(n) numel(setdiff(B,A{n})) < numel(B),1:numel(A)));
toc, clear Result

disp('------------------------  With arrayfun + intersect')
tic
Result = A(arrayfun(@(n) ~isempty(intersect(B,A{n})),1:numel(A)));
toc, clear Result

disp('************************  With cellfun **************************')
disp('------------------------  With cellfun + ismember')
tic
Result = A(cellfun(@(x)any(ismember(B,x)), A));
toc, clear Result

disp('------------------------  With cellfun + bsxfun')
tic
Result = A(cellfun(@(x) any(any(bsxfun(@eq,B(:),x),2)),A));
toc, clear Result

disp('------------------------  With cellfun + setdiff')
tic
Result = A(cellfun(@(x) numel(setdiff(B,x)) < numel(B),A));
toc, clear Result

disp('------------------------  With cellfun + setdiff')
tic
Result = A(cellfun(@(x) ~isempty(intersect(B,x)),A));

disp('************************  With masking bsxfun **************************')
tic
lens = cellfun('length',A); %// number of elements in each cell of A
mask = bsxfun(@ge,lens,(1:max(lens))'); %//'
A_numarr = NaN(size(mask));
A_numarr(mask) = [A{:}];
Result = A(any(any(bsxfun(@eq,A_numarr,permute(B,[1 3 2])),1),3));
toc

可以看出,基于************************ With arrayfun ************************** ------------------------ With arrayfun + ismember Elapsed time is 0.409810 seconds. ------------------------ With arrayfun + bsxfun Elapsed time is 0.157327 seconds. ------------------------ With arrayfun + setdiff Elapsed time is 1.154602 seconds. ------------------------ With arrayfun + intersect Elapsed time is 1.081729 seconds. ************************ With cellfun ************************** ------------------------ With cellfun + ismember Elapsed time is 0.392375 seconds. ------------------------ With cellfun + bsxfun Elapsed time is 0.143341 seconds. ------------------------ With cellfun + setdiff Elapsed time is 1.101331 seconds. ------------------------ With cellfun + setdiff ************************ With masking bsxfun ******************** Elapsed time is 0.067224 seconds. 的解决方案比基于cellfun的解决方案快一点!此外,基于掩码的arrayfun方法看起来很有趣,但请记住它是内存饥饿的性质