Bytt om elementer i et array i JavaScript


Finnes det en enklere måte å bytte to elementer i en array på?

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

Svar #1

Du trenger bare én midlertidig variabel.

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

Eller med ES6 og senere:

Gitt arrayet arr=[1,2,3,4], kan du nå bytte verdier på én linje slik:

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

Dette ville produsere arrayet [2,1,3,4]. Dette er destrukturerende tildeling.

Svar #2

Hvis du vil ha et enkelt uttrykk, og bruker ren JavaScript, husk at returverdien fra en splice-operasjon inneholder elementet/elementene som ble fjernet.

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"

[0] er nødvendig på slutten av uttrykket siden Array.splice() returnerer en tabell, og i denne situasjonen trenger vi det enkelte elementet i den returnerte tabellen.

Svar #3

Ifølge en tilfeldig person på Metafilter, «Nylige versjoner av Javascript [sic] lar deg gjøre bytter (blant annet) mye penere:»

[ list[x], list[y] ] = [ list[y], list[x] ];

Mine raske tester viste at denne Python-lignende koden fungerer bra i den versjonen av JavaScript som for øyeblikket brukes i "Google Apps Script" (".gs"). Dessverre viser videre tester at denne koden gir en "Uncaught ReferenceError: Invalid left-hand side in assignment." i hvilken som helst versjon av JavaScript (".js") som brukes av Google Chrome Version 24.0.1312.57 m.

Svar #4

Dette virker greit....

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

Imidlertid bruk

var b = list[y];

betyr at en b-variabel vil være til stede for resten av området. Dette kan potensielt føre til en minnelekkasje. Usannsynlig, men fortsatt bedre å unngå.

Kanskje en god idé å legge dette inn i Array.prototype.swap

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

som kan kalles slik:

list.swap( x, y )

Dette er en ren tilnærming til både å unngå minnelekkasjer og DRY.

Svar #5

Vel, du trenger ikke å bufre begge verdiene - bare én:

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

Svar #6

Du kan bytte elementer i en matrise på følgende måte:

list[x] = [list[y],list[y]=list[x]][0]

Se følgende eksempel:

list = [1,2,3,4,5]
list[1] = [list[3],list[3]=list[1]][0]
//list is now [1,4,3,2,5]

Merk: det fungerer på samme måte for vanlige variabler

var a=1,b=5;
a = [b,b=a][0]

Svar #7

ES2015 (ES6) introduserte array-destructuring, som lar deg skrive det som følger:

let a = 1, b = 2;
// a: 1, b: 2
[a, b] = [b, a];
// a: 2, b: 1

Svar #8

Vurder en slik løsning uten behov for å definere den tredje variabelen:

function swap(arr, from, to) {
  arr.splice(from, 1, arr.splice(to, 1, arr[from])[0]);
}

var letters = ["a", "b", "c", "d", "e", "f"];

swap(letters, 1, 4);

console.log(letters); // ["a", "e", "c", "d", "b", "f"]

Merk: Du vil kanskje legge til ekstra kontroller, for eksempel for array-lengde. Denne løsningen er muterbar, så swap-funksjonen trenger ikke å returnere en ny array, den gjør bare endringer på arrayen som er sendt inn.

Svar #9

Med numeriske verdier kan du unngå en midlertidig variabel ved å bruke bitvis XOR:

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

Eller en aritmetisk sum (merk at dette kun fungerer hvis x + y er mindre enn den maksimale verdien for datatypen):

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

Svar #10

For å bytte to påfølgende elementer i en array:

array.splice(IndexToSwap, 2, array[IndexToSwap + 1], array[IndexToSwap]);

Svar #11

Bruk destrukturerende tildeling:

var arr = [1, 2, 3, 4]
[arr[index1], arr[index2]] = [arr[index2], arr[index1]]

som også kan utvides til

[src order elements] => [dest order elements]

Svar #12

For to eller flere elementer (fast antall)

[list[y], list[x]] = [list[x], list[y]];

Ingen midlertidig variabel nødvendig!

Jeg tenkte på å ganske enkelt kalle list.reverse().
Men så innså jeg at det bare ville fungere som en bytteoperasjon når list.length=x + y + 1.

For variabelt antall elementer

Jeg har sett på ulike moderne Javascript-konstruksjoner for dette formålet, inkludert Map og map, men dessverre har ingen resultert i en kode som var mer kompakt eller raskere enn denne gammeldagse, løkke-baserte konstruksjonen:

function multiswap(arr,i0,i1) {/* argument immutable if string */
    if (arr.split) return multiswap(arr.split(""), i0, i1).join("");
    var diff = [];
    for (let i in i0) diff[i0[i]] = arr[i1[i]];
    return Object.assign(arr,diff);
}

Example:
    var alphabet = "abcdefghijklmnopqrstuvwxyz";
    var [x,y,z] = [14,6,15];
    var output = document.getElementsByTagName("code");
    output[0].innerHTML = alphabet;
    output[1].innerHTML = multiswap(alphabet, [0,25], [25,0]);
    output[2].innerHTML = multiswap(alphabet, [0,25,z,1,y,x], [25,0,x,y,z,3]);
<table>
    <tr><td>Input:</td>                        <td><code></code></td></tr>
    <tr><td>Swap two elements:</td>            <td><code></code></td></tr>
    <tr><td>Swap multiple elements:&nbsp;</td> <td><code></code></td></tr>
</table>

Svar #13

Utdrag fra Enkeltlinjet JavaScript-variabelbytte for heltall:

var a = 5, b = 9;    
b = (a += b -= a) - b;    
alert([a, b]); // Alerts "9, 5"

Relaterte artikler