Move an array element from one array position to another

JavascriptArrays

Javascript Problem Overview


I'm having a hard time figuring out how to move an element of an array. For example, given the following:

var array = [ 'a', 'b', 'c', 'd', 'e'];

How can I write a function to move the element 'd' to the left of 'b' ?

Or 'a' to the right of 'c'?

After moving the elements, the indexes of the rest of the elements should be updated. The resulting array would be:

array = ['a', 'd', 'b', 'c', 'e']

This seems like it should be pretty simple, but I can't wrap my head around it.

Javascript Solutions


Solution 1 - Javascript

If you'd like a version on npm, array-move is the closest to this answer, although it's not the same implementation. See its usage section for more details. The previous version of this answer (that modified Array.prototype.move) can be found on npm at array.prototype.move.


I had fairly good success with this function:

function array_move(arr, old_index, new_index) {
    if (new_index >= arr.length) {
        var k = new_index - arr.length + 1;
        while (k--) {
            arr.push(undefined);
        }
    }
    arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
    return arr; // for testing
};

// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1)); 

Note that the last return is simply for testing purposes: splice performs operations on the array in-place, so a return is not necessary. By extension, this move is an in-place operation. If you want to avoid that and return a copy, use slice.

Stepping through the code:

  1. If new_index is greater than the length of the array, we want (I presume) to pad the array properly with new undefineds. This little snippet handles this by pushing undefined on the array until we have the proper length.
  2. Then, in arr.splice(old_index, 1)[0], we splice out the old element. splice returns the element that was spliced out, but it's in an array. In our above example, this was [1]. So we take the first index of that array to get the raw 1 there.
  3. Then we use splice to insert this element in the new_index's place. Since we padded the array above if new_index > arr.length, it will probably appear in the right place, unless they've done something strange like pass in a negative number.

A fancier version to account for negative indices:

function array_move(arr, old_index, new_index) {
    while (old_index < 0) {
        old_index += arr.length;
    }
    while (new_index < 0) {
        new_index += arr.length;
    }
    if (new_index >= arr.length) {
        var k = new_index - arr.length + 1;
        while (k--) {
            arr.push(undefined);
        }
    }
    arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
    return arr; // for testing purposes
};
    
// returns [1, 3, 2]
console.log(array_move([1, 2, 3], -1, -2));

Which should account for things like array_move([1, 2, 3], -1, -2) properly (move the last element to the second to last place). Result for that should be [1, 3, 2].

Either way, in your original question, you would do array_move(arr, 0, 2) for a after c. For d before b, you would do array_move(arr, 3, 1).

Solution 2 - Javascript

I like this way. It's concise and it works.

function arraymove(arr, fromIndex, toIndex) {
    var element = arr[fromIndex];
    arr.splice(fromIndex, 1);
    arr.splice(toIndex, 0, element);
}

Note: always remember to check your array bounds.

Run Snippet in jsFiddle

Solution 3 - Javascript

Here's a one liner I found on JSPerf....

Array.prototype.move = function(from, to) {
    this.splice(to, 0, this.splice(from, 1)[0]);
};

which is awesome to read, but if you want performance (in small data sets) try...

 Array.prototype.move2 = function(pos1, pos2) {
    // local variables
    var i, tmp;
    // cast input parameters to integers
    pos1 = parseInt(pos1, 10);
    pos2 = parseInt(pos2, 10);
    // if positions are different and inside array
    if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) {
      // save element from position 1
      tmp = this[pos1];
      // move element down and shift other elements up
      if (pos1 < pos2) {
        for (i = pos1; i < pos2; i++) {
          this[i] = this[i + 1];
        }
      }
      // move element up and shift other elements down
      else {
        for (i = pos1; i > pos2; i--) {
          this[i] = this[i - 1];
        }
      }
      // put element from position 1 to destination
      this[pos2] = tmp;
    }
  }

I can't take any credit, it should all go to Richard Scarrott. It beats the splice based method for smaller data sets in this performance test. It is however significantly slower on larger data sets as Darwayne points out.

Solution 4 - Javascript

> The splice() method adds/removes items to/from an array, and returns the removed item(s). > > Note: This method changes the original array. /w3schools/

Array.prototype.move = function(from,to){
  this.splice(to,0,this.splice(from,1)[0]);
  return this;
};

var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(3,1);//["a", "d", "b", "c", "e"]


var arr = [ 'a', 'b', 'c', 'd', 'e'];
arr.move(0,2);//["b", "c", "a", "d", "e"]

as the function is chainable this works too:

alert(arr.move(0,2).join(','));

demo here

Solution 5 - Javascript

My 2c. Easy to read, it works, it's fast, it doesn't create new arrays.

function move(array, from, to) {
  if( to === from ) return array;

  var target = array[from];                         
  var increment = to < from ? -1 : 1;

  for(var k = from; k != to; k += increment){
    array[k] = array[k + increment];
  }
  array[to] = target;
  return array;
}

Solution 6 - Javascript

Got this idea from @Reid of pushing something in the place of the item that is supposed to be moved to keep the array size constant. That does simplify calculations. Also, pushing an empty object has the added benefits of being able to search for it uniquely later on. This works because two objects are not equal until they are referring to the same object.

({}) == ({}); // false

So here's the function which takes in the source array, and the source, destination indexes. You could add it to the Array.prototype if needed.

function moveObjectAtIndex(array, sourceIndex, destIndex) {
	var placeholder = {};
	// remove the object from its initial position and
	// plant the placeholder object in its place to
    // keep the array length constant
	var objectToMove = array.splice(sourceIndex, 1, placeholder)[0];
	// place the object in the desired position
	array.splice(destIndex, 0, objectToMove);
	// take out the temporary object
	array.splice(array.indexOf(placeholder), 1);
}

Solution 7 - Javascript

Here is my one liner ES6 solution with an optional parameter on.

if (typeof Array.prototype.move === "undefined") {
  Array.prototype.move = function(from, to, on = 1) {
    this.splice(to, 0, ...this.splice(from, on))
  }
}

Adaptation of the first solution proposed by digiguru

The parameter on is the number of element starting from from you want to move.

Here is a chainable variation of this:

if (typeof Array.prototype.move === "undefined") {
  Array.prototype.move = function(from, to, on = 1) {
    return this.splice(to, 0, ...this.splice(from, on)), this
  }
}

[3, 4, 5, 1, 2].move(3, 0, 2) // => [1, 2, 3, 4, 5]

If you'd like to avoid prototype pollution, here's a stand-alone function:

function move(array, from, to, on = 1) {
  return array.splice(to, 0, ...array.splice(from, on)), array
}

move([3, 4, 5, 1, 2], 3, 0, 2) // => [1, 2, 3, 4, 5]

And finally, here's a pure function that doesn't mutate the original array:

function moved(array, from, to, on = 1) {
  return array = array.slice(), array.splice(to, 0, ...array.splice(from, on)), array
}

This should cover basically every variation seen in every other answer.

Solution 8 - Javascript

This is based on @Reid's solution. Except:

  • I'm not changing the Array prototype.
  • Moving an item out of bounds to the right does not create undefined items, it just moves the item to the right-most position.

Function:

function move(array, oldIndex, newIndex) {
    if (newIndex >= array.length) {
        newIndex = array.length - 1;
    }
    array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
    return array;
}

Unit tests:

describe('ArrayHelper', function () {
    it('Move right', function () {
        let array = [1, 2, 3];
        arrayHelper.move(array, 0, 1);
        assert.equal(array[0], 2);
        assert.equal(array[1], 1);
        assert.equal(array[2], 3);
    })
    it('Move left', function () {
        let array = [1, 2, 3];
        arrayHelper.move(array, 1, 0);
        assert.equal(array[0], 2);
        assert.equal(array[1], 1);
        assert.equal(array[2], 3);
    });
    it('Move out of bounds to the left', function () {
        let array = [1, 2, 3];
        arrayHelper.move(array, 1, -2);
        assert.equal(array[0], 2);
        assert.equal(array[1], 1);
        assert.equal(array[2], 3);
    });
    it('Move out of bounds to the right', function () {
        let array = [1, 2, 3];
        arrayHelper.move(array, 1, 4);
        assert.equal(array[0], 1);
        assert.equal(array[1], 3);
        assert.equal(array[2], 2);
    });
});

Solution 9 - Javascript

You can implement some basic calculus and create a universal function for moving array elements from one position to the other.

For JavaScript it looks like this:

function magicFunction (targetArray, indexFrom, indexTo) { 

    targetElement = targetArray[indexFrom]; 
    magicIncrement = (indexTo - indexFrom) / Math.abs (indexTo - indexFrom); 

    for (Element = indexFrom; Element != indexTo; Element += magicIncrement){ 
        targetArray[Element] = targetArray[Element + magicIncrement]; 
    } 

    targetArray[indexTo] = targetElement; 

}

Check out "moving array elements" at "Gloommatter" for detailed explanation.

https://web.archive.org/web/20121105042534/http://www.gloommatter.com:80/DDesign/programming/moving-any-array-elements-universal-function.html

Solution 10 - Javascript

I've implemented an immutable ECMAScript 6 solution based off of @Merc's answer over here:

const moveItemInArrayFromIndexToIndex = (array, fromIndex, toIndex) => {
  if (fromIndex === toIndex) return array;

  const newArray = [...array];

  const target = newArray[fromIndex];
  const inc = toIndex < fromIndex ? -1 : 1;

  for (let i = fromIndex; i !== toIndex; i += inc) {
    newArray[i] = newArray[i + inc];
  }

  newArray[toIndex] = target;

  return newArray;
};

The variable names can be shortened, just used long ones so that the code can explain itself.

Solution 11 - Javascript

One approach would be to create a new array with the pieces in the order you want, using the slice method.

Example

var arr = [ 'a', 'b', 'c', 'd', 'e'];
var arr2 = arr.slice(0,1).concat( ['d'] ).concat( arr.slice(2,4) ).concat( arr.slice(4) );
  • arr.slice(0,1) gives you ['a']
  • arr.slice(2,4) gives you ['b', 'c']
  • arr.slice(4) gives you ['e']

Solution 12 - Javascript

The splice method of Array might help: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice

Just keep in mind it might be relatively expensive since it has to actively re-index the array.

Solution 13 - Javascript

Another pure JS variant using ES6 array spread operator with no mutation

const reorder = (array, sourceIndex, destinationIndex) => {
	const smallerIndex = Math.min(sourceIndex, destinationIndex);
	const largerIndex = Math.max(sourceIndex, destinationIndex);

	return [
		...array.slice(0, smallerIndex),
		...(sourceIndex < destinationIndex
			? array.slice(smallerIndex + 1, largerIndex + 1)
			: []),
		array[sourceIndex],
		...(sourceIndex > destinationIndex
			? array.slice(smallerIndex, largerIndex)
			: []),
		...array.slice(largerIndex + 1),
	];
}

// returns ['a', 'c', 'd', 'e', 'b', 'f']
console.log(reorder(['a', 'b', 'c', 'd', 'e', 'f'], 1, 4))
      
 

Solution 14 - Javascript

I needed an immutable move method (one that didn't change the original array), so I adapted @Reid's accepted answer to simply use Object.assign to create a copy of the array before doing the splice.

Array.prototype.immutableMove = function (old_index, new_index) {
  var copy = Object.assign([], this);
  if (new_index >= copy.length) {
      var k = new_index - copy.length;
      while ((k--) + 1) {
          copy.push(undefined);
      }
  }
  copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
  return copy;
};

Here is a jsfiddle showing it in action.

Solution 15 - Javascript

Here's one way to do it in an immutable way. It handles negative numbers as well as an added bonus. This is reduces number of possible bugs at the cost of performance compared to editing the original array.

const numbers = [1, 2, 3];
const moveElement = (array, from, to) => {
  const copy = [...array];
  const valueToMove = copy.splice(from, 1)[0];
  copy.splice(to, 0, valueToMove);
  return copy;
};

console.log(moveElement(numbers, 0, 2))
// > [2, 3, 1]
console.log(moveElement(numbers, -1, -3))
// > [3, 1, 2] 

Solution 16 - Javascript

    Array.prototype.moveUp = function (value, by) {
        var index = this.indexOf(value),
            newPos = index - (by || 1);

        if (index === -1)
            throw new Error("Element not found in array");

        if (newPos < 0)
            newPos = 0;

        this.splice(index, 1);
        this.splice(newPos, 0, value);
    };

    Array.prototype.moveDown = function (value, by) {
        var index = this.indexOf(value),
            newPos = index + (by || 1);

        if (index === -1)
            throw new Error("Element not found in array");

        if (newPos >= this.length)
            newPos = this.length;

        this.splice(index, 1);
        this.splice(newPos, 0, value);
    };



    var arr = ['banana', 'curyWurst', 'pc', 'remembaHaruMembaru'];

    alert('withiout changes= '+arr[0]+' ||| '+arr[1]+' ||| '+arr[2]+' ||| '+arr[3]);
    arr.moveDown(arr[2]);


    alert('third word moved down= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);
    arr.moveUp(arr[2]);
    alert('third word moved up= '+arr[0] + ' ||| ' + arr[1] + ' ||| ' + arr[2] + ' ||| ' + arr[3]);

http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview

Solution 17 - Javascript

I love immutable, functional one liners :) ...

const swapIndex = (array, from, to) => (
  from < to 
    ? [...array.slice(0, from), ...array.slice(from + 1, to + 1), array[from], ...array.slice(to + 1)] 
    : [...array.slice(0, to), array[from], ...array.slice(to, from), ...array.slice(from + 1)]
);

Solution 18 - Javascript

I ended up combining two of these to work a little better when moving both small and large distances. I get fairly consistent results, but this could probably be tweaked a little bit by someone smarter than me to work differently for different sizes, etc.

Using some of the other methods when moving objects small distances was significantly faster (x10) than using splice. This might change depending on the array lengths though, but it is true for large arrays.

function ArrayMove(array, from, to) {
    if ( Math.abs(from - to) > 60) {
        array.splice(to, 0, array.splice(from, 1)[0]);
    } else {
        // works better when we are not moving things very far
        var target = array[from];
        var inc = (to - from) / Math.abs(to - from);
        var current = from;
        for (; current != to; current += inc) {
            array[current] = array[current + inc];
        }
        array[to] = target;    
    }
}

https://web.archive.org/web/20181026015711/https://jsperf.com/arraymove-many-sizes

Solution 19 - Javascript

It is stated in many places (https://stackoverflow.com/questions/948358/adding-custom-functions-into-array-prototype) playing with the Array prototype could be a bad idea, anyway I combined the best from various posts, I came with this, using modern Javascript:

    Object.defineProperty(Array.prototype, 'immutableMove', {
        enumerable: false,
        value: function (old_index, new_index) {
            var copy = Object.assign([], this)
            if (new_index >= copy.length) {
                var k = new_index - copy.length;
                while ((k--) + 1) { copy.push(undefined); }
            }
            copy.splice(new_index, 0, copy.splice(old_index, 1)[0]);
            return copy
        }
    });

    //how to use it
    myArray=[0, 1, 2, 3, 4];
    myArray=myArray.immutableMove(2, 4);
    console.log(myArray);
    //result: 0, 1, 3, 4, 2

Hope can be useful to anyone

Solution 20 - Javascript

This version isn't ideal for all purposes, and not everyone likes comma expressions, but here's a one-liner that's a pure expression, creating a fresh copy:

const move = (from, to, ...a) => (a.splice(to, 0, ...a.splice(from, 1)), a)

A slightly performance-improved version returns the input array if no move is needed, it's still OK for immutable use, as the array won't change, and it's still a pure expression:

const move = (from, to, ...a) => 
    from === to 
    ? a 
    : (a.splice(to, 0, ...a.splice(from, 1)), a)

The invocation of either is

const shuffled = move(fromIndex, toIndex, ...list)

i.e. it relies on spreading to generate a fresh copy. Using a fixed arity 3 move would jeopardize either the single expression property, or the non-destructive nature, or the performance benefit of splice. Again, it's more of an example that meets some criteria than a suggestion for production use.

Solution 21 - Javascript

const move = (from, to, ...a) =>from === to ? a : (a.splice(to, 0, ...a.splice(from, 1)), a);
const moved = move(0, 2, ...['a', 'b', 'c']);
console.log(moved)

Solution 22 - Javascript

I thought this was a swap problem but it's not. Here's my one-liner solution:

const move = (arr, from, to) => arr.map((item, i) => i === to ? arr[from] : (i >= Math.min(from, to) && i <= Math.max(from, to) ? arr[i + Math.sign(to - from)] : item));

Here's a small test:

let test = ['a', 'b', 'c', 'd', 'e'];
console.log(move(test, 0, 2)); // [ 'b', 'c', 'a', 'd', 'e' ]
console.log(move(test, 1, 3)); // [ 'a', 'c', 'd', 'b', 'e' ]
console.log(move(test, 2, 4)); // [ 'a', 'b', 'd', 'e', 'c' ]
console.log(move(test, 2, 0)); // [ 'c', 'a', 'b', 'd', 'e' ]
console.log(move(test, 3, 1)); // [ 'a', 'd', 'b', 'c', 'e' ]
console.log(move(test, 4, 2)); // [ 'a', 'b', 'e', 'c', 'd' ]
console.log(move(test, 4, 0)); // [ 'e', 'a', 'b', 'c', 'd' ]

Solution 23 - Javascript

This is a really simple method using splice

Array.prototype.moveToStart = function(index) {
    this.splice(0, 0, this.splice(index, 1)[0]);
    return this;
  };

Solution 24 - Javascript

Array.move.js

Summary

Moves elements within an array, returning an array containing the moved elements.

Syntax

array.move(index, howMany, toIndex);

Parameters

index: Index at which to move elements. If negative, index will start from the end.

howMany: Number of elements to move from index.

toIndex: Index of the array at which to place the moved elements. If negative, toIndex will start from the end.

Usage

array = ["a", "b", "c", "d", "e", "f", "g"];

array.move(3, 2, 1); // returns ["d","e"]

array; // returns ["a", "d", "e", "b", "c", "f", "g"]

Polyfill

Array.prototype.move || Object.defineProperty(Array.prototype, "move", {
	value: function (index, howMany, toIndex) {
		var
		array = this,
		index = parseInt(index) || 0,
		index = index < 0 ? array.length + index : index,
		toIndex = parseInt(toIndex) || 0,
		toIndex = toIndex < 0 ? array.length + toIndex : toIndex,
		toIndex = toIndex <= index ? toIndex : toIndex <= index + howMany ? index : toIndex - howMany,
		moved;

		array.splice.apply(array, [toIndex, 0].concat(moved = array.splice(index, howMany)));

		return moved;
	}
});

Solution 25 - Javascript

I used the nice answer of @Reid, but struggled with moving an element from the end of an array one step further - to the beginning (like in a loop). E.g. ['a', 'b', 'c'] should become ['c', 'a', 'b'] by calling .move(2,3)

I achieved this by changing the case for new_index >= this.length.

Array.prototype.move = function (old_index, new_index) {
		console.log(old_index + " " + new_index);
		while (old_index < 0) {
			old_index += this.length;
		}
		while (new_index < 0) {
			new_index += this.length;
		}
		if (new_index >= this.length) {
			new_index = new_index % this.length;
		}
		this.splice(new_index, 0, this.splice(old_index, 1)[0]);
		return this; // for testing purposes
	};

Solution 26 - Javascript

As an addition to Reid's excellent answer (and because I cannot comment); You can use modulo to make both negative indices and too large indices "roll over":

function array_move(arr, old_index, new_index) {
  new_index =((new_index % arr.length) + arr.length) % arr.length;
  arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
  return arr; // for testing
}

// returns [2, 1, 3]
console.log(array_move([1, 2, 3], 0, 1)); 

Solution 27 - Javascript

let ar = ['a', 'b', 'c', 'd'];

function change( old_array, old_index , new_index ){
  
  return old_array.map(( item , index, array )=>{
    if( index === old_index ) return array[ new_index ];
    else if( index === new_index ) return array[ old_index ];
    else return item;
  });
  
}

let result = change( ar, 0, 1 );

console.log( result );

result:

["b", "a", "c", "d"]

Solution 28 - Javascript

var ELEMS = ['a', 'b', 'c', 'd', 'e'];
/*
    Source item will remove and it will be placed just after destination
*/
function moveItemTo(sourceItem, destItem, elements) {
    var sourceIndex = elements.indexOf(sourceItem);
    var destIndex = elements.indexOf(destItem);
    if (sourceIndex >= -1 && destIndex > -1) {
        elements.splice(destIndex, 0, elements.splice(sourceIndex, 1)[0]);
    }
    return elements;
}
console.log('Init: ', ELEMS);
var result = moveItemTo('a', 'c', ELEMS);
console.log('BeforeAfter: ', result);

Solution 29 - Javascript

One approach would be to use splice() to remove the item from the array and then by using the splice() method once again, insert the removed item into the target index.

const array = ['a', 'b', 'c', 'd', 'e']

const newArray = moveItem(array, 3, 1) // move element from index 3 to index 1

function moveItem(arr, fromIndex, toIndex){
  let itemRemoved = arr.splice(fromIndex, 1) // assign the removed item as an array
  arr.splice(toIndex, 0, itemRemoved[0]) // insert itemRemoved into the target index
  return arr
}

console.log(newArray)

Solution 30 - Javascript

    let oldi, newi, arr;
    
    if(newi !== oldi) {
      let el = this.arr.splice(oldi, 1);
      if(newi > oldi && newi === (this.arr.length + 2)) {
        this.arr.push("");
      }
      this.arr.splice(newi, 0, el);
      if(newi > oldi && newi === (this.arr.length + 2)) {
        this.arr.pop();
      }
    }

Solution 31 - Javascript

Immutable version without array copy:

const moveInArray = (arr, fromIndex, toIndex) => {
  if (toIndex === fromIndex || toIndex >= arr.length) return arr;

  const toMove = arr[fromIndex];
  const movedForward = fromIndex < toIndex;

  return arr.reduce((res, next, index) => {
    if (index === fromIndex) return res;
    if (index === toIndex) return res.concat(
      movedForward ? [next, toMove] : [toMove, next]
    );

    return res.concat(next);
  }, []);
};

Solution 32 - Javascript

I think the best way is define a new property for Arrays

Object.defineProperty(Array.prototype, 'move', {
	value: function (old_index, new_index) {
		while (old_index < 0) {
			old_index += this.length;
		}
		while (new_index < 0) {
			new_index += this.length;
		}
		if (new_index >= this.length) {
			let k = new_index - this.length;
			while ((k--) + 1) {
				this.push(undefined);
			}
		}
		this.splice(new_index, 0, this.splice(old_index, 1)[0]);
		return this;
	}
});

console.log([10, 20, 30, 40, 50].move(0, 1));  // [20, 10, 30, 40, 50]
console.log([10, 20, 30, 40, 50].move(0, 2));  // [20, 30, 10, 40, 50]

Solution 33 - Javascript

This method will preserve the original array, and check for bounding errors.

const move = (from, to, arr) => {
    to = Math.max(to,0)
    from > to 
        ? [].concat(
            arr.slice(0,to), 
            arr[from], 
            arr.filter((x,i) => i != from).slice(to)) 
        : to > from
            ? [].concat(
                arr.slice(0, from), 
                arr.slice(from + 1, to + 1), 
                arr[from], 
                arr.slice(to + 1))
            : arr}

Solution 34 - Javascript

In your example, because is an array of string we can use a ranking object to reorder the string array:

let rank =  { 'a': 0, 'b': 1, 'c': 2, 'd': 0.5, 'e': 4 };
arr.sort( (i, j) => rank[i] - rank[j] );

We can use this approach to write a move function that works on a string array:

function stringArrayMove(arr, from, to)
{
  let rank = arr.reduce( (p, c, i) => ( p[c] = i, p ), ({ }) );
  // rank = { 'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4 }
  rank[arr[from]] = to - 0.5;
  // rank = { 'a': 0, 'b': 1, 'c': 2, 'd': 1.5, 'e': 4 }
  arr.sort( (i, j) => rank[i] - rank[j] );
  // arr = [ 'a', 'd', 'b', 'c', 'e' ];
}

let arr = [ 'a', 'b', 'c', 'd', 'e' ];
stringArrayMove(arr, 3, 1);
console.log( JSON.stringify(arr) );

If, however, the thing we wanted to sort is an array of object, we can introduce the ranking as a new property of each object, i.e.

let arr = [ { value: 'a', rank: 0 },            { value: 'b', rank: 1 },            { value: 'c', rank: 2 },            { value: 'd', rank: 0.5 },            { value: 'e', rank: 4 } ];
arr.sort( (i, j) => i['rank'] - j['rank'] );

We can use Symbol to hide the visibility of this property, i.e. it will not be shown in JSON.stringify. We can generalize this in an objectArrayMove function:

function objectArrayMove(arr, from, to) {
  let rank = Symbol("rank");
  arr.forEach( (item, i) => item[rank] = i );
  arr[from][rank] = to - 0.5;
  arr.sort( (i, j) => i[rank] - j[rank]);
}
let arr = [ { value: 'a' }, { value: 'b' }, { value: 'c' }, { value: 'd' }, { value: 'e' } ];
console.log( 'array before move: ', JSON.stringify( arr ) );
// array before move:  [{"value":"a"},{"value":"b"},{"value":"c"},{"value":"d"},{"value":"e"}]
objectArrayMove(arr, 3, 1);
console.log( 'array after move: ', JSON.stringify( arr ) );
// array after move:  [{"value":"a"},{"value":"d"},{"value":"b"},{"value":"c"},{"value":"e"}]

Solution 35 - Javascript

If the object is nested:

  let array = ['a', 'b', 'c', 'd', 'e'];
  let existingElement = JSON.parse(JSON.stringify(array[3]));
  array.splice(1, 0, existingElement);
  array.splice(4, 1);
  console.log(array)

Solution 36 - Javascript

I resolved my issue using immutability-helper library.

import update from 'immutability-helper';

const move = (arr: any[], from: number, to: number) => update(arr, {
  $splice: [
    [from, 1],
    [to, 0, arr[from] as string],
  ],
});

const testArray = ['a', 'b', 'c', 'd', 'e'];
console.log(move(testArray, 1, 3)); // [ 'c', 'b', 'c', 'd', 'e' ]
console.log(move(testArray, 4, 0)); // [ 'e', 'b', 'c', 'd', 'a' ]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark BrownView Question on Stackoverflow
Solution 1 - JavascriptReidView Answer on Stackoverflow
Solution 2 - JavascriptSteakOverflowView Answer on Stackoverflow
Solution 3 - JavascriptdigiguruView Answer on Stackoverflow
Solution 4 - Javascriptuser669677View Answer on Stackoverflow
Solution 5 - JavascriptMercView Answer on Stackoverflow
Solution 6 - JavascriptAnuragView Answer on Stackoverflow
Solution 7 - JavascriptElie TeyssedouView Answer on Stackoverflow
Solution 8 - JavascriptAndre PenaView Answer on Stackoverflow
Solution 9 - JavascriptAndreaView Answer on Stackoverflow
Solution 10 - JavascriptBarry Michael DoyleView Answer on Stackoverflow
Solution 11 - JavascriptJared UpdikeView Answer on Stackoverflow
Solution 12 - JavascriptKen FranqueiroView Answer on Stackoverflow
Solution 13 - JavascriptabrView Answer on Stackoverflow
Solution 14 - JavascriptJavid JamaeView Answer on Stackoverflow
Solution 15 - JavascriptCavemanView Answer on Stackoverflow
Solution 16 - JavascriptArthur TsidkilovView Answer on Stackoverflow
Solution 17 - JavascriptDudley CraigView Answer on Stackoverflow
Solution 18 - JavascriptAndrewView Answer on Stackoverflow
Solution 19 - JavascriptBernieSFView Answer on Stackoverflow
Solution 20 - JavascriptRobert MonferaView Answer on Stackoverflow
Solution 21 - JavascriptShijo RsView Answer on Stackoverflow
Solution 22 - Javascriptcagdas_ucarView Answer on Stackoverflow
Solution 23 - JavascriptNour AdelView Answer on Stackoverflow
Solution 24 - JavascriptJonathan NealView Answer on Stackoverflow
Solution 25 - JavascriptMarcel BöttcherView Answer on Stackoverflow
Solution 26 - JavascriptDidiView Answer on Stackoverflow
Solution 27 - JavascriptNaycho334View Answer on Stackoverflow
Solution 28 - JavascriptMohd Abdul BaqueeView Answer on Stackoverflow
Solution 29 - JavascriptGassView Answer on Stackoverflow
Solution 30 - JavascriptbehnamView Answer on Stackoverflow
Solution 31 - JavascriptVoloshinSView Answer on Stackoverflow
Solution 32 - JavascriptiProDevView Answer on Stackoverflow
Solution 33 - Javascriptnikk wongView Answer on Stackoverflow
Solution 34 - JavascriptStephen QuanView Answer on Stackoverflow
Solution 35 - JavascriptleonccView Answer on Stackoverflow
Solution 36 - JavascriptMaqsood AhmedView Answer on Stackoverflow