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: </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"
