2013-06-13 5 views
5

Gibt es ein Äquivalent zu bsxfun für nicht numerische Daten?Verwenden von `bsxfun` für nicht numerische Daten

Zum Beispiel möchte ich alle Paare von Strings in zwei Zellenarrays gespeichert vergleichen:

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

Ich immer am Ende Schleife ... Sie können versuchen, diese Erweiterung Anfrage an TMW einzureichen. – Oleg

Antwort

3

Angst, ich bin es keine solche Entsprechung für Zell-Arrays :-(

Was wie ich sehe, können Sie entweder:

  1. Folgen Oleg Anregung und Verwendung Schleifen
  2. Nutzung bestehender Implementierungen wie mAryCellFcn oder csxfun aus dem Dateiaustausch.
  3. Rollen Sie Ihre eigene Funktion. Zum Beispiel, hier ist eine Variante von Robert Idee, die für die Eingänge aller Dimensionen arbeitet (unter den Beschränkungen des bsxfun, natürlich) und eine beliebige binäre Funktion 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); 
    

    Wenn Ihre Funktion kann auf ganze Zellen-Arrays Element arbeiten -wise, könnten Sie eine Singleton Expansion auf dem Zellenanordnungen führen Sie zuerst, und dann direkt füttern auf die Funktion 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)); 
    

    die letztere Methode schneller sein könnte, wenn func für vektorisiert Operationen auf Zellen-Arrays optimiert ist.

+2

'csxfun' ist nicht gut; das ist nur 'cellfun' und sonst nichts. 'maryCellFcn' sieht gut aus ... –

+0

@RodyOldenhuis Danke, dass du das bemerkt hast! –

+1

@EitanT, +1, nette! –

2

Wie wäre es

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

?

+1

(aber dann wieder, ich denke, Shai ist auf der Suche nach einem allgemeinen Ansatz, der 'bsxfun' ersetzen könnte mehr als nur diese Strings vergleichen) –

+0

@RobertP. - Du hast recht. Ich habe 'strcmp' als Beispiel benutzt. – Shai

4

Ich mag Rody's solution, aber Sie könnte tun auch eine Abhilfe wie folgt aus:

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

+1. Dies würde nicht die richtigen Abmessungen für 2D/3D-Arrays geben. Wie auch immer, ich habe Ihre Frage an Arbeiten an Zellen-Arrays angepasst, genau wie das Original "bsxfun" (hoffe, es macht Ihnen nichts aus). –

+0

@EitanT, natürlich nicht! –

2

Da die Fehlermeldung sagt, arbeitet Rundfunk nur für numerische Typen. Hier sind andere mögliche Alternativen:

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))