2013-06-13 11 views
5

Esiste un valore equivalente a bsxfun per i dati non numerici?Utilizzo di `bsxfun` per i dati non numerici

Per esempio, voglio mettere a confronto tutte le coppie di stringhe memorizzate in due cell-array:

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

Ho sempre finito il ciclo ... Puoi provare a inviare questa richiesta di miglioramento a TMW. – Oleg

risposta

3

Temo che non esiste un'equivalente per cell-array :-(

Per quanto come posso vedere, è possibile:

  1. suggestione e l'utilizzo Segui Oleg loop
  2. utilizzare le implementazioni esistenti, come mAryCellFcn o csxfun dallo scambio di file.
  3. Roll your own function. Ad esempio, ecco una variante dell'idea di Robert che funziona per input di qualsiasi dimensione (sotto le restrizioni della bsxfun, ovviamente) e una funzione binaria arbitraria 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); 
    

    Se la funzione può operare su tutto l'elemento matrici di celle -wise, è possibile eseguire un'espansione singleton sui tuoi matrici di celle di prima, e poi alimentano direttamente alla funzione 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)); 
    

    quest'ultimo metodo potrebbe essere più veloce se func è ottimizzato per le operazioni vettorializzate su matrici di celle.

+2

'csxfun' non va bene; è solo "cellfun" e nient'altro. 'mAryCellFcn' sembra buono anche se ... –

+0

@RodyOldenhuis Grazie per averlo notato! –

+1

@EitanT, +1, bello! –

2

Come su

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

?

+1

(ma ripeto, suppongo che Shai stia cercando un approccio generale che possa sostituire 'bsxfun' per qualcosa di più del semplice confronto di queste stringhe) –

+0

@RobertP. - hai ragione. Stavo usando 'strcmp' come esempio. – Shai

4

mi piace Rody's solution, ma si potrebbe fare anche una soluzione del genere:

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

+1. Ciò non fornirebbe le dimensioni corrette per gli array 2D/3D. Ad ogni modo, ho adattato la tua domanda a lavori su array di celle come l'originale 'bsxfun' (spero non ti dispiaccia). –

+0

@EitanT, ovviamente no! –

2

Come dice il messaggio di errore, la trasmissione funziona solo per i tipi numerici. Ecco altre possibili alternative:

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