Comment puis-je itérer chaque élément dans une matrice n-dimensionnelle dans MATLAB?
j'ai un problème. Je dois itérer chaque élément d'une matrice n-dimensionnelle dans MATLAB. Le problème est, Je ne sais pas comment faire pour un nombre arbitraire de dimensions. Je sais que je peux dire
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
et ainsi de suite, mais est-il une façon de le faire pour un nombre arbitraire de dimensions?
8 réponses
vous pouvez utiliser l'indexation linéaire pour accéder à chaque élément.
for idx = 1:numel(array)
element = array(idx)
....
end
c'est utile si vous n'avez pas besoin de savoir ce que je,j,k, Vous êtes. Toutefois, si vous n'avez pas besoin de savoir quel indice vous êtes, vous êtes probablement mieux d'utiliser arrayfun()
l'idée d'un index linéaire pour les tableaux dans matlab est importante. Un tableau dans MATLAB est vraiment juste un vecteur d'éléments, tendu dans la mémoire. MATLAB vous permet d'utiliser soit un index de ligne et de colonne, soit un index linéaire simple. Par exemple,
A = magic(3)
A =
8 1 6
3 5 7
4 9 2
A(2,3)
ans =
7
A(8)
ans =
7
Nous pouvons voir l'ordre les éléments sont stockés dans la mémoire, en déroulant le tableau dans un vecteur.
A(:)
ans =
8
3
4
1
5
9
6
7
2
comme vous pouvez le voir, le 8ème élément est le nombre 7. En fait, l' la fonction find renvoie ses résultats sous forme d'index linéaire.
find(A>6)
ans =
1
6
8
le résultat est, nous pouvons accéder à chaque élément à tour de rôle d'un tableau n-d général en utilisant une boucle unique. Par exemple, si nous voulions mettre les éléments de A (Oui, je sais qu'il y a de meilleures façons de le faire), on pourrait le faire:
B = zeros(size(A));
for i = 1:numel(A)
B(i) = A(i).^2;
end
B
B =
64 1 36
9 25 49
16 81 4
dans de nombreuses circonstances, l'indice linéaire est plus utile. Conversion entre l'indice linéaire et deux indices dimensionnels (ou plus) est accompli avec les fonctions sub2ind et ind2sub.
l'index linéaire s'applique en général à tout tableau de matlab. Vous pouvez donc l'utiliser sur des structures, des réseaux de cellules, etc. Le seul problème avec l'indice linéaire est quand ils deviennent trop grands. MATLAB utilise un entier 32 bits pour stocker ces index. Donc, si votre tableau contient plus qu'un total de 2^32 éléments, l'indice linéaire échouera. Ce n'est vraiment qu'un problème si vous utilisez souvent des matrices éparses, alors que cela causer un problème. (Bien que je n'utilise pas une version 64 bits de MATLAB, je pense que ce problème a été résolu pour les chanceux qui le font.)
comme indiqué dans quelques autres réponses, vous pouvez itérer sur tous les éléments dans une matrice a (de n'importe quelle dimension) en utilisant un index linéaire de 1 à numel(a) dans un simple pour boucle. Il y a quelques autres trucs que vous pouvez utiliser: ARRAYFUN et CELLFUN .
supposons d'abord que vous avez une fonction que vous voulez appliquer à chaque élément de Un (appelé "my_func"). Vous créez d'abord un poignée de fonction à cette fonction:
fcn = @my_func;
si A est une matrice (de type double, simple, etc.) de dimension arbitraire, vous pouvez utiliser ARRAYFUN pour appliquer "my_func" à chaque élément:
outArgs = arrayfun(fcn,A);
si A est un tableau de cellules de dimension arbitraire, vous pouvez utiliser CELLFUN pour appliquer "my_func" à chaque cellule:
outArgs = cellfun(fcn,A);
la fonction" my_func "doit accepter A comme entrée. S'il y a des sorties de "my_func", elles sont placées dans outArgs , qui seront de la même taille/dimension que a .
Une mise en garde sur les produits... si "my_func" renvoie des sorties de tailles et de types différents lorsqu'il fonctionne sur différents éléments de A , alors est exclu. devra être transformé en réseau de cellules. Ceci est fait en appelant soit ARRAYFUN ou CELLFUN avec une paire de paramètres/valeurs supplémentaires:
outArgs = arrayfun(fcn,A,'UniformOutput',false);
outArgs = cellfun(fcn,A,'UniformOutput',false);
Une autre astuce consiste à utiliser ind2sub
et sub2ind
. En conjonction avec numel
et size
, cela peut vous permettre de faire des choses comme ce qui suit, qui crée un tableau n-dimensionnel, puis définit tous les éléments sur la" diagonale " pour être 1.
d = zeros( 3, 4, 5, 6 ); % Let's pretend this is a user input
nel = numel( d );
sz = size( d );
szargs = cell( 1, ndims( d ) ); % We'll use this with ind2sub in the loop
for ii=1:nel
[ szargs{:} ] = ind2sub( sz, ii ); % Convert linear index back to subscripts
if all( [szargs{2:end}] == szargs{1} ) % On the diagonal?
d( ii ) = 1;
end
end
Vous pourriez faire une fonction récursive faire le travail
- Let
L = size(M)
- Let
idx = zeros(L,1)
- prendre
length(L)
comme profondeur maximale - Boucle
for idx(depth) = 1:L(depth)
- si votre profondeur est
length(L)
, faites l'opération de l'élément, sinon appelez à nouveau la fonction avecdepth+1
pas aussi rapide que les méthodes vectorisées si vous voulez de vérifier tous les points, mais si vous n'avez pas besoin d'évaluer la plupart d'entre eux, il peut être tout à fait un économiseur de temps.
ces solutions sont plus rapides (environ 11%) que l'utilisation de numel
;)
for idx = reshape(array,1,[]),
element = element + idx;
end
ou
for idx = array(:)',
element = element + idx;
end
UPD. tnx @rayryeng pour les erreurs détectées dans la dernière réponse
Avertissement
l'information de synchronisation que ce post a référencé est incorrecte et inexacte en raison d'une faute de frappe fondamentale qui a été faite (voir le flux de commentaires ci-dessous ainsi que le modifier l'histoire - regarder la première version de cette réponse). Caveat Emptor .
Si vous plus que les autres utilisations de size
vous pouvez voir que vous pouvez réellement obtenir un vecteur de la taille de chaque dimension. Ce lien vous montre la documentation:
www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html
après avoir obtenu le vecteur de taille, itérez sur ce vecteur. Quelque chose comme ceci (pardonnez ma syntaxe puisque je n'ai pas utilisé Matlab depuis l'Université):
d = size(m);
dims = ndims(m);
for dimNumber = 1:dims
for i = 1:d[dimNumber]
...
faites-en une syntaxe Matlab-légale, et je pense que ça ferait ce que vous voulez.
aussi, vous devriez être en mesure de faire L'indexation linéaire comme décrit ici .
vous voulez simuler n-imité pour les boucles.
itérant à travers n-dimensional array peut être vu comme augmentant le nombre de n-chiffre.
à chaque dimmension nous avons autant de chiffres que la longueur de la dimmension.
exemple:
supposons que nous ayons un tableau(matrix)
int[][][] T=new int[3][4][5];
dans "pour la notation" nous avons:
for(int x=0;x<3;x++)
for(int y=0;y<4;y++)
for(int z=0;z<5;z++)
T[x][y][z]=...
pour simuler ce que vous devrait utiliser la "notation du nombre à n chiffres "
nous avons un numéro à 3 chiffres, avec 3 chiffres pour le premier, 4 pour le deuxième et cinq pour le troisième chiffre
nous devons augmenter le nombre, donc nous obtiendrions la séquence
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
0 1 3
0 1 4
0 2 0
0 2 1
0 2 2
0 2 3
0 2 4
0 3 0
0 3 1
0 3 2
0 3 3
0 3 4
and so on
pour que vous puissiez écrire le code pour augmenter un tel nombre de n-chiffres. Vous pouvez le faire de telle façon que vous pouvez commencer avec n'importe quelle valeur du nombre et augmenter/diminuer les chiffres par des nombres. De cette façon, vous pouvez simuler emboîté pour les boucles qui commencent quelque part dans la table et finissent pas à la fin.
Ce n'est pas une tâche facile. Je ne peux malheureusement pas vous aider avec la notation matlab.