Using `bsxfun` for non-numeric data

别说谁变了你拦得住时间么 提交于 2019-12-01 18:09:34

I'm afraid there's no such equivalent for cell-arrays :-(

As far as I can see, you can either:

  1. Follow Oleg's suggestion and use loops
  2. Use existing implementations such as mAryCellFcn or csxfun from the File Exchange.
  3. Roll your own function. For example, here's a variant of Robert's idea that works for inputs of any dimensions (under the restrictions of bsxfun, of course) and an arbitrary binary function func:

    function C = mybsxfun(func, A, B)
        idx_A = reshape(1:numel(A), size(A));
        idx_B = reshape(1:numel(B), size(B));
        C = bsxfun(@(ii, jj)func(A(ii), B(jj)), idx_A, idx_B);
    

    If your function can operate on entire cell arrays element-wise, you could perform a singleton expansion on your cell arrays first, and then feed them directly to the function func:

    mask = bsxfun(@or, true(size(A)), true(size(B)));
    idx_A = bsxfun(@times, mask, reshape(1:numel(A), size(A)));
    idx_B = bsxfun(@times, mask, reshape(1:numel(B), size(B)));
    C = func(A(idx_A), B(idx_B));
    

    The latter method might be faster if func is optimized for vectorized operations on cell arrays.

Stewie Griffin

I like Rody's solution, but you could also do a workaround like this:

ia=(1:length(a)).'; ib=1:length(b);
a=a(:);
bsxfun(@(ii,jj) strcmp(  a(ii),b(jj) )  ,ia, ib);

How about

[str,ia,ib] = intersect(a,b)

?

As the error message says, broadcasting only works for numeric types. Here are other possible alternatives:

a = {'aa', 'bb', 'cc'};
b = {'dd'; 'aa'};

%# obviously doesnt work
%#bsxfun(@strcmp, a, b)

%# do the singleton expansion ourselves
strcmp(repmat(a,size(b)), repmat(b,size(a)))

%# if you dislike REPMAT, we can use Tony's trick
strcmp(a(ones(size(b)),:), b(:,ones(size(a))))

%# we could also use CELLFUN
cell2mat(cellfun(@(s)strcmp(a,s), b, 'UniformOutput',false))
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!