Is there any simpler way to swap two elements in an array?
var a = list[x], b = list[y]; list[y] = a; list[x] = b;
Is there any simpler way to swap two elements in an array?
var a = list[x], b = list[y]; list[y] = a; list[x] = b;
You only need one temporary variable.
var b = list[y]; list[y] = list[x]; list[x] = b;
If you want a single expression, using native javascript, remember that the return value from a splice operation contains the element(s) that was removed.
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:
The [0]
is necessary at the end of the expression as Array.splice()
returns an array, and in this situation we require the single element in the returned array.
This seems ok....
var b = list[y]; list[y] = list[x]; list[x] = b;
Howerver using
var b = list[y];
means a b variable is going to be to be present for the rest of the scope. This can potentially lead to a memory leak. Unlikely, but still better to avoid.
Maybe a good idea to put this into Array.prototype.swap
Array.prototype.swap = function (x,y) { var b = this[x]; this[x] = this[y]; this[y] = b; return this; }
which can be called like:
list.swap( x, y )
This is a clean approach to both avoiding memory leaks and DRY.
Well, you don't need to buffer both values - only one:
var tmp = list[x]; list[x] = list[y]; list[y] = tmp;
With numeric values you can avoid a temporary variable by using bitwise xor
list[x] = list[x] ^ list[y]; list[y] = list[y] ^ list[x]; list[x] = list[x] ^ list[y];
or an arithmetic sum (noting that this only works if x + y is less than the maximum value for the data type)
list[x] = list[x] + list[y]; list[y] = list[x] - list[y]; list[x] = list[x] - list[y];
You can swap elements in an array the following way:
list[x] = [list[y],list[y]=list[x]][0]
See the following example:
list = [1,2,3,4,5] list[1] = [list[3],list[3]=list[1]][0] //list is now [1,4,3,2,5]
Note: it works the same way for regular variables
var a=1,b=5; a = [b,b=a][0]
According to some random person on Metafilter, "Recent versions of Javascript allow you to do swaps (among other things) much more neatly:"
[ list[x], list[y] ] = [ list[y], list[x] ];
My quick tests showed that this Pythonic code works great in the version of JavaScript currently used in "Google Apps Script" (".gs"). Alas, further tests show this code gives a "Uncaught ReferenceError: Invalid left-hand side in assignment." in whatever version of JavaScript (".js") is used by Google Chrome Version 24.0.1312.57 m.
Digest from http://www.greywyvern.com/?post=265
var a = 5, b = 9; b = (a += b -= a) - b; alert([a, b]); // alerts "9, 5"
To swap two consecutive elements of array
array.splice(IndexToSwap,2,array[IndexToSwap+1],array[IndexToSwap]);
You can swap any number of objects or literals, even of different types, using a simple identity function like this:
var swap = function (x){return x}; b = swap(a, a=b); c = swap(a, a=b, b=c);
For your problem:
var swap = function (x){return x}; list[y] = swap(list[x], list[x]=list[y]);
This works in JavaScript because it accepts additional arguments even if they are not declared or used. The assignments a=b
etc, happen after a
is passed into the function.
var a = [1,2,3,4,5], b=a.length; for (var i=0; i
This didn't exist 7 years ago but no with the new hot sauce of es2015 and up you can use array destructuring to
var a = 1, b = 2; [a, b] = [b, a]; --> a = 2, b = 1
[list[y], list[x]] = [list[x], list[y]];
No temporary variable required!
I was thinking about simply calling list.reverse()
.
But then I realised it would work as swap only when list.length = x + y + 1
.
I have looked into various modern Javascript constructions to this effect, including Map and map, but sadly none has resulted in a code that was more compact or faster than this old-fashioned, loop-based construction:
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]);
Input:
Swap two elements:
There is one interesting way of swapping:
var a = 1; var b = 2; [a,b] = [b,a];
(ES6 way)
Here's a compact version swaps value at i1 with i2 in arr
arr.slice(0,i1).concat(arr[i2],arr.slice(i1+1,i2),arr[i1],arr.slice(i2+1))
Here's a one-liner that doesn't mutate list
:
let newList = Object.assign([], list, {[x]: list[y], [y]: list[x]})
(Uses language features not available in 2009 when the question was posted!)
what about Destructuring_assignment
var arr = [1, 2, 3, 4] [arr[index1], arr[index2]] = [arr[index2], arr[index1]]
which can also be extended to
[src order elements] => [dest order elements]
Here is a variation that first checks if the index exists in the array:
Array.prototype.swapItems = function(a, b){ if( !(a in this) || !(b in this) ) return this; this[a] = this.splice(b, 1, this[a])[0]; return this; }
It currently will just return this
if the index does not exist, but you could easily modify behavior on fail
Just for the fun of it, another way without using any extra variable would be:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // swap index 0 and 2 arr[arr.length] = arr[0]; // copy idx1 to the end of the array arr[0] = arr[2]; // copy idx2 to idx1 arr[2] = arr[arr.length-1]; // copy idx1 to idx2 arr.length--; // remove idx1 (was added to the end of the array) console.log( arr ); // -> [3, 2, 1, 4, 5, 6, 7, 8, 9]
If need swap first and last elements only:
array.unshift( array.pop() );
Here is the correct way to do it:
Array.prototype.swap = function(a, b) { var temp = this[a]; this[a] = this[b]; this[b] = temp; };
Usage:
var myArray = [0,1,2,3,4...]; myArray.swap(4,1);