345 votes

Javascript échange les éléments d'un tableau

Existe-t-il un moyen plus simple de permuter deux éléments dans un tableau ?

var a = list[x], b = list[y];
list[y] = a;
list[x] = b;

686voto

tvanfosson Points 268301

Vous n'avez besoin que d'une seule variable temporaire.

var b = list[y];
list[y] = list[x];
list[x] = b;

Modifier détourner la meilleure réponse 10 ans plus tard, avec beaucoup d'adoption de l'ES6 à notre actif :

Étant donné le tableau arr = [1,2,3,4] vous pouvez maintenant échanger les valeurs dans une ligne comme suit :

[arr[0], arr[1]] = [arr[1], arr[0]];

Cela produirait le tableau [2,1,3,4] . C'est affectation destructrice .

8 votes

Même sans utiliser ECMAScript 6 Destructuring Assignment, il est possible de réaliser un échange simultané sans polluer la portée actuelle avec une variable temporaire : a = [b, b = a][0]; comme l'a souligné @Jan Bien que je me retrouve toujours à utiliser l'approche des variables temporaires car elle est inter-langages (par exemple C/C++) et la première approche qui me vient à l'esprit.

6 votes

Vous pouvez échanger en place (muter) avec es6 comme d'autres le montrent ci-dessous : [ list[y], list[x] ] = [ list[x], list[y] ];

0 votes

[arr[0], arr[1]] = [arr[1], arr[0]] ne produire que [2, 1] sans le reste du tableau

133voto

kennebec Points 33886

Si vous voulez une seule expression, utilisez le javascript natif, rappelez-vous que la valeur de retour d'une opération de fractionnement contient le ou les éléments qui ont été supprimés.

var A = [1, 2, 3, 4, 5, 6, 7, 8, 9], x= 0, y= 1;
A[x] = A.splice(y, 1, A[x])[0];
alert(A); // alerts "2,1,3,4,5,6,7,8,9"

Edit :

Le site [0] est nécessaire à la fin de l'expression comme Array.splice() renvoie un tableau, et dans cette situation, nous avons besoin de l'unique élément du tableau renvoyé.

4 votes

Splice renvoie un tableau. Ainsi, dans votre exemple, après l'opération d'échange, votre tableau ressemble en fait à : [[2], 1, 3, 4, 5, 6, 7, 8, 9]

1 votes

A[x]= A.splice(y, 1, A[x])[0] ; ? in mootools Array.implement({ swap : function(x, y) { this[y] = this.splice(x, 1, this[y])[0] ; } }) ;

0 votes

Confirmé, le [0] est manquant.

82voto

Stefan Points 2043

Cela semble correct....

var b = list[y];
list[y] = list[x];
list[x] = b;

Howerver utilise

var b = list[y];

signifie un b va être présente pour le reste de la portée. Cela peut potentiellement conduire à une fuite de mémoire. Peu probable, mais il vaut mieux l'éviter.

Peut-être une bonne idée de mettre ceci dans Array.prototype.swap

Array.prototype.swap = function (x,y) {
  var b = this[x];
  this[x] = this[y];
  this[y] = b;
  return this;
}

qui peut être appelé comme :

list.swap( x, y )

Il s'agit d'une approche propre à la fois éviter les fuites de mémoire et SEC .

0 votes

J'aime aussi ceci. Array.implement({swap : function(x,y) { x = this[x] ; this[x] = this[y] ; this[y] = x ; return this ; } }) ;

1 votes

C'est bien. Peut-être une vérification des limites ? Array.prototype.swap = function (x,y) { if (x >= 0 && x < this.length && y >= 0 && y < this.length) { var b = this[x]; this[x] = this[y]; this[y] = b; } return this; };

0 votes

@DavidR. La vérification des limites est superflue et inutile. L'appelant a tout ce qui est nécessaire pour effectuer une telle vérification si cela est souhaité, bien que dans la plupart des cas vous savez déjà que x et y sont dans les limites parce que vous êtes dans une boucle d'une certaine sorte.

33voto

Marc Gravell Points 482669

Eh bien, vous n'avez pas besoin de tamponner les deux valeurs - une seule :

var tmp = list[x];
list[x] = list[y];
list[y] = tmp;

18 votes

Votre 'tmp' semble plus raisonnable à utiliser que 'b'.

2 votes

@ofir_aghai oui, vous avez raison : il y a plus de 10 ans, une autre réponse a été postée. 22 secondes avant celui-ci (12:14:16Z vs 12:14:38Z)...

1 votes

En temps normal, je m'y tenais. mais juste parce que la question des secondes et le respect de votre CV de 10 ans ici ;-)

18voto

Jakub Arnold Points 21204

Avec des valeurs numériques, vous pouvez éviter d'utiliser une variable temporaire en utilisant la fonction xor en mode bit.

list[x] = list[x] ^ list[y];
list[y] = list[y] ^ list[x];
list[x] = list[x] ^ list[y];

ou une somme arithmétique (à noter que cela ne fonctionne que si x + y est inférieur à la valeur maximale pour le type de données)

list[x] = list[x] + list[y];
list[y] = list[x] - list[y];
list[x] = list[x] - list[y];

2 votes

Est-ce que c'est Dark comme dans Vador ? +1

7 votes

Il y a un problème. Il n'y a pas list[y] = list[x] - list[x]; équivaut juste à list[y] = 0; ?

3 votes

L'astuce xor échoue également lorsque x=y -- elle met la liste[x] à zéro, alors qu'on pourrait s'attendre à ce qu'elle conserve la valeur originale de la liste[x].

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X