J'ai un tableau de cellules composé de nombres, de chaînes et de tableaux vides. Je veux trouver la position (linéaire ou indexée) de toutes les cellules contenant une chaîne dans laquelle une certaine sous-chaîne d'intérêt apparaît.

mixedCellArray = {
   'adpo' 2134  []
   0 [] 'daesad'
   'xxxxx' 'dp' 'dpdpd'
}

Si la sous-chaîne d'intérêt est «dp», alors je devrais obtenir les indices pour trois cellules.

Les seules solutions que je peux trouver fonctionnent lorsque le tableau de cellules ne contient que des chaînes:

Une solution consiste à rechercher toutes les cellules ne contenant pas de chaînes et à les remplir avec '', comme l'indique cette publication. Malheureusement, mon approche nécessite une variante de cette solution, probablement quelque chose comme cellfun('ischar',mixedCellArray). Cela provoque l'erreur:

Error using cellfun
Unknown option. 

Merci pour toutes suggestions sur la façon de résoudre l'erreur.

J'ai publié ceci sur usenet

APRÈS-MIDI ÉDUCATIF: Pour ceux qui n'ont pas Matlab à la maison et qui finissent par faire des va-et-vient entre Matlab et Octave. J'ai demandé ci-dessus pourquoi cellfun n'accepte pas 'ischar' comme premier argument. La réponse s'avère être que l'argument doit être un handle de fonction dans Matlab, donc vous devez vraiment passer @ischar. Il existe des fonctions dont les noms peuvent être passés sous forme de chaînes, pour des raisons de compatibilité ascendante, mais ischar n'en fait pas partie.

1
user36800 25 janv. 2017 à 03:24

4 réponses

Meilleure réponse

Que diriez-vous de ce one-liner:

>> mixedCellArray = {'adpo' 2134  []; 0 [] 'daesad'; 'xxxxx' 'dp' 'dpdpd'};
>> index = cellfun(@(c) ischar(c) && ~isempty(strfind(c, 'dp')), mixedCellArray)

index =

  3×3 logical array

   1   0   0
   0   0   0
   0   1   1

Vous pourriez vous en passer sans le ischar(c) && ..., mais vous voudrez probablement le conserver car strfind convertira implicitement toutes les valeurs numériques / tableaux en leurs caractères ASCII équivalents pour effectuer la comparaison. Cela signifie que vous pourriez obtenir de faux positifs, comme dans cet exemple:

>> C = {65, 'A'; 'BAD' [66 65 68]}  % Note there's a vector in there

C =

  2×2 cell array

    [ 65]    'A'         
    'BAD'    [1×3 double]

>> index = cellfun(@(c) ~isempty(strfind(c, 'A')), C)  % Removed ischar(c) &&

index =

  2×2 logical array

   1   1                % They all match!
   1   1
4
gnovice 25 janv. 2017 à 18:04

Utilisez simplement une boucle et testez avec ischar et < a href = "https://www.mathworks.com/help/matlab/ref/contains.html" rel = "nofollow noreferrer"> contains (ajouté dans R2016b). Les différents *fun sont essentiellement des boucles et, en général, n'offrent aucun avantage de performance par rapport à la boucle explicite.

mixedCellArray = {'adpo' 2134  []; 0 [] 'daesad'; 'xxxxx' 'dp' 'dpdpd'};
querystr = 'dp';

test = false(size(mixedCellArray));
for ii = 1:numel(mixedCellArray)
    if ischar(mixedCellArray{ii})
        test(ii) = contains(mixedCellArray{ii}, querystr);
    end
end

Qui retourne:

test =

  3×3 logical array

   1   0   0
   0   0   0
   0   1   1

Éditer:

Si vous n'avez pas de version MATLAB avec contains, vous pouvez remplacer un regex:

test(ii) = ~isempty(regexp(mixedCellArray{ii}, querystr, 'once'));
4
excaza 25 janv. 2017 à 01:09
z=cellfun(@(x)strfind(x,'dp'),mixedCellArray,'un',0);
idx=cellfun(@(x)x>0,z,'un',0);
find(~cellfun(@isempty,idx))
2
PURUSHOTTAMA 25 janv. 2017 à 10:05

Voici une solution à partir du lien usenet dans mon message d'origine:

>> mixedCellArray = {
         'adpo' 2134  []
         0 [] 'daesad'
         'xxxxx' 'dp' 'dpdpd'
      }

mixedCellArray =
    'adpo'     [2134]          []
    [    0]        []    'daesad'
    'xxxxx'    'dp'      'dpdpd'

>> ~cellfun( @isempty , ...
             cellfun( @(x)strfind(x,'dp') , ...
                      mixedCellArray , ...
                      'uniform',0) ...
           )

ans =
     1     0     0
     0     0     0
     0     1     1

Le cellfun interne est capable d'appliquer strfind même à des cellules numériques car, je suppose, Matlab traite les tableaux numériques et les chaînes de la même manière. Une chaîne est juste un tableau de nombres représentant les codes de caractères. Le cellfun externe identifie toutes les cellules pour lesquelles le cellfun interne a trouvé une correspondance, et le préfixe tilde le transforme en toutes les cellules pour lesquelles il n'y avait AUCUNE correspondance.

Merci à dpb.

0
user36800 25 janv. 2017 à 17:37