2013-06-13 11 views
5

Czy istnieje odpowiednik bsxfun dla danych nieliczbowych?Używanie `bsxfun` dla danych nieliczbowych

Na przykład, chcę porównać wszystkie pary strun przechowywane w dwóch tablicach komórkowymi:

>> a = {'aa', 'bb', 'cc'}; 
>> b = {'dd', 'aa'}; 
>> bsxfun(@strcmp, a, b'); % not working for cells :-(
+3

Zawsze kończę pętle ... Możesz spróbować przesłać to rozszerzenie do TMW. – Oleg

Odpowiedz

3

Obawiam się, że nie ma takich odpowiednik dla komórek-tablic :-(

Jak daleko jak widzę, można:

  1. sugestia i korzystania śledź Olega pętle
  2. wykorzystać istniejące implementacje takich jak mAryCellFcn lub csxfun z Wymiana plików.
  3. Rzuć własną funkcję. Na przykład, oto wariant idei Roberta, który działa dla wejść o dowolnych wymiarach (w ramach ograniczeń bsxfun, oczywiście) i dowolna funkcja binarna 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); 
    

    Jeśli funkcja może działać na całej macierzy komórek elementu -wise, można wykonać singleton ekspansję na swoich tablicach komórkowych, a potem karmić je bezpośrednio do funkcji 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)); 
    

    Ta ostatnia metoda może być szybciej, jeśli func jest zoptymalizowany do operacji na macierzach vectorized komórkowych.

+2

'csxfun' nie jest dobre; to tylko "celofonia" i nic więcej. 'mAryCellFcn' wygląda dobrze mimo ... –

+0

@RodyOldenhuis Dzięki za zauważenie tego! –

+1

@EitanT, +1, niezły! –

2

Jak o

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

?

+1

(ale znowu, myślę, że Shai szuka ogólnego podejścia, które mogłoby zastąpić 'bsxfun' dla czegoś więcej niż tylko porównywanie tych łańcuchów) –

+0

@RobertP. - masz rację. Użyłem 'strcmp' jako przykład. – Shai

4

Lubię Rody's solution, ale mógłby również zrobić obejście tak:

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

+1. Nie dałoby to prawidłowych wymiarów dla tablic 2D/3D. Jednak dostosowałem twoje pytanie do prac nad tablicami komórek, tak jak oryginalny "bsxfun" (mam nadzieję, że nie masz nic przeciwko). –

+0

@EntanT, oczywiście, że nie! –

2

Jak mówi komunikat o błędzie, nadawanie działa tylko dla typów numerycznych. Oto inne możliwe alternatywy:

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)) 
Powiązane problemy