2013-06-13 8 views
5

Y at-il un équivalent à bsxfun pour les données non numériques?Utiliser `bsxfun` pour les données non numériques

Par exemple, je veux comparer toutes les paires de chaînes stockées dans deux tableaux de cellules:

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

Je finis toujours par boucler ... Vous pouvez essayer de soumettre cette demande d'amélioration à TMW. – Oleg

Répondre

3

Je crains qu'il n'y ait pas un tel équivalent pour les tableaux de cellules :-(

En ce qui concerne que je peux voir, vous pouvez:

  1. suggestion et de l'utilisation Suivre Oleg boucles
  2. Utilisez les implémentations existantes telles que mAryCellFcn ou csxfun à partir de l'échange de fichiers.
  3. Jouez votre propre fonction. Par exemple, voici une variante de l'idée de Robert qui fonctionne pour les entrées de toutes les dimensions (sous réserve des restrictions de bsxfun, bien sûr) et une fonction binaire arbitraire 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); 
    

    Si votre fonction peut fonctionner sur l'élément ensemble des réseaux de cellules -wise, vous pouvez effectuer une expansion singleton sur vos réseaux de cellules d'abord, puis les transmettre directement à la fonction 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)); 
    

    Cette dernière méthode peut être plus rapide si func est optimisée pour les opérations vectorisées sur des réseaux cellulaires.

+2

'csxfun' n'est pas bon; c'est juste 'cellfun' et rien d'autre. 'mAryCellFcn' semble bon ... –

+0

@RodyOldenhuis Merci d'avoir remarqué ça! –

+1

@EitanT, +1, gentil! –

2

Que diriez-vous

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

?

+1

(mais là encore, je suppose que Shai est à la recherche d'une approche générale qui pourrait se substituer 'bsxfun' pour plus de simplement comparer ces chaînes) –

+0

@RobertP. - tu as raison. J'utilisais 'strcmp' comme exemple. – Shai

4

J'aime Rody's solution, mais vous pourrait aussi faire une solution de contournement comme ceci:

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

+1. Cela ne donnerait pas les dimensions correctes pour les tableaux 2D/3D. Cependant, j'ai adapté votre question aux travaux sur les tableaux de cellules, tout comme l'original 'bsxfun' (j'espère que cela ne vous dérange pas). –

+0

@EitanT, bien sûr que non! –

2

Comme le message d'erreur indique, la diffusion ne fonctionne que pour les types numériques. Voici d'autres alternatives possibles:

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