142

Say, I have an array that looks like this:

var playlist = [ {artist:"Herbie Hancock", title:"Thrust"}, {artist:"Lalo Schifrin", title:"Shifting Gears"}, {artist:"Faze-O", title:"Riding High"} ]; 

How can I move an element to another position?

I want to move for example, {artist:"Lalo Schifrin", title:"Shifting Gears"} to the end.

I tried using splice, like this:

var tmp = playlist.splice(2,1); playlist.splice(2,0,tmp); 

But it doesn't work.

1
  • 3
    What does "doesn't work" mean -- does it throw an error, does it change nothing, does it change your array in a way you didn't intend? It looks reasonable to me. Commented Mar 14, 2010 at 0:41

14 Answers 14

318

The syntax of Array.splice is:

yourArray.splice(index, howmany, element1, /*.....,*/ elementX); 

Where:

  • index is the position in the array you want to start removing elements from
  • howmany is how many elements you want to remove from index
  • element1, ..., elementX are elements you want inserted from position index.

This means that splice() can be used to remove elements, add elements, or replace elements in an array, depending on the arguments you pass.

Note that it returns an array of the removed elements.

Something nice and generic would be:

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

Then just use:

var ar = [1,2,3,4,5]; ar.move(0,3); alert(ar) // 2,3,4,1,5 

Diagram:

Algorithm diagram

Sign up to request clarification or add additional context in comments.

2 Comments

This is a good answer, and the splice() within a splice() does the job well. It should be noted, however, that adding a move() method to the Array prototype is called "Monkey Patching" and is typically considered bad practice. stackoverflow.com/questions/5741877/…
Seems tricky using splice() there are some edge cases that are difficult to solve - that is in the case of reordering more than two items at a time.
32

If you know the indexes you could easily swap the elements, with a simple function like this:

function swapElement(array, indexA, indexB) { var tmp = array[indexA]; array[indexA] = array[indexB]; array[indexB] = tmp; } swapElement(playlist, 1, 2); // [{"artist":"Herbie Hancock","title":"Thrust"}, // {"artist":"Faze-O","title":"Riding High"}, // {"artist":"Lalo Schifrin","title":"Shifting Gears"}] 

Array indexes are just properties of the array object, so you can swap its values.

1 Comment

Thanks, @CMS. If I swap mean's don't want to replace the order...For Example, If I select the 3rd object to 1 st position I want to swap 1 as a 2 and 2 as a 3 as 1
24

With ES6 you can do something like this:

const swapPositions = (array, a ,b) => { [array[a], array[b]] = [array[b], array[a]] } let array = [1,2,3,4,5]; swapPositions(array,0,1); /// => [2, 1, 3, 4, 5] 

1 Comment

This swaps the two element's positions. Question is for reorder.
19

Here is an immutable version for those who are interested:

function immutableMove(arr, from, to) { return arr.reduce((prev, current, idx, self) => { if (from === to) { prev.push(current); } if (idx === from) { return prev; } if (from < to) { prev.push(current); } if (idx === to) { prev.push(self[from]); } if (from > to) { prev.push(current); } return prev; }, []); } 

3 Comments

Hi, could you explain to me the benefits of this function over the answer above ?
This solution does not modify the original element but returns a new array with the entry being moved.
@Xogno It is especially useful in frameworks like React that often requires immutable objects in order to detect changes
11

You could always use the sort method, if you don't know where the record is at present:

playlist.sort(function (a, b) { return a.artist == "Lalo Schifrin" ? 1 // Move it down the list : 0; // Keep it the same }); 

2 Comments

What about return +(a.artist == "Lalo Schifrin")
@Funko you could do that, if you prefer brevity over verbosity.
9

Change 2 to 1 as the first parameter in the splice call when removing the element:

var tmp = playlist.splice(1, 1); playlist.splice(2, 0, tmp[0]); 

1 Comment

it should be playlist.splice(2,0,tmp[0]); Right?
9

Immutable version, no side effects (doesn’t mutate original array):

const testArr = [1, 2, 3, 4, 5]; function move(from, to, arr) { const newArr = [...arr]; const item = newArr.splice(from, 1)[0]; newArr.splice(to, 0, item); return newArr; } console.log(move(3, 1, testArr)); // [1, 4, 2, 3, 5] 

codepen: https://codepen.io/mliq/pen/KKNyJZr

Comments

3

EDIT: Please check out Andy's answer as his answer came first and this is solely an extension of his

I know this is an old question, but I think it's worth it to include Array.prototype.sort().

Here's an example from MDN along with the link

var numbers = [4, 2, 5, 1, 3]; numbers.sort(function(a, b) { return a - b; }); console.log(numbers); // [1, 2, 3, 4, 5] 

Luckily it doesn't only work with numbers:

arr.sort([compareFunction])

compareFunction

Specifies a function that defines the sort order. If omitted, the array is sorted according to each character's Unicode code point value, according to the string conversion of each element.

I noticed that you're ordering them by first name:

let playlist = [ {artist:"Herbie Hancock", title:"Thrust"}, {artist:"Lalo Schifrin", title:"Shifting Gears"}, {artist:"Faze-O", title:"Riding High"} ]; // sort by name playlist.sort((a, b) => { if(a.artist < b.artist) { return -1; } if(a.artist > b.artist) { return 1; } // else names must be equal return 0; }); 

note that if you wanted to order them by last name you would have to either have a key for both first_name & last_name or do some regex magic, which I can't do XD

Hope that helps :)

3 Comments

This should be an edit to or comment on this answer.
@JaredSmith Oops! I didn't see his answer. I don't have enough points or whatever to edit his question, and I don't think all of this information should be added in a comment. So until someone edits his question I'll simply add that this is an extension to Andy E's answer(like I should of done).
I thinks it's fine now :)
2

Time complexity of all answers is O(n^2) because had used twice spice. But O(n/2) is possible.

Most Perfomance Solution:

  • Array with n elements,
  • x is to, y is from
  • should be n >x && n > y

time complexity should be |y - x|. So its is number of elements that is between from and to.

  • bestcase: O(1); //ex: from:4 to:5
  • average : O(n/2)
  • worthcase : O(n) //ex: from:0 to:n

function reOrder(from,to,arr) { if(from == to || from < 0 || to < 0 ) { return arr}; var moveNumber = arr[from]; if(from < to) { for(var i =from; i< to; i++){ arr[i] = arr[i+1] } } else{ for(var i = from; i > to; i--){ arr[i] = arr[i-1]; } } arr[to] = moveNumber; return arr; } var arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]; console.log(reOrder(3,7,arr));

1 Comment

for(var i =from; i< to; i++) should be for(var i =from; i< to-1; i++) as moving down means leaving the from empty so it has to be shifted
1

Try this:

playlist = playlist.concat(playlist.splice(1, 1)); 

Comments

1

If you only ever want to move one item from an arbitrary position to the end of the array, this should work:

function toEnd(list, position) { list.push(list.splice(position, 1)); return list; } 

If you want to move multiple items from some arbitrary position to the end, you can do:

function toEnd(list, from, count) { list.push.apply(list, list.splice(from, count)); return list; } 

If you want to move multiple items from some arbitrary position to some arbitrary position, try:

function move(list, from, count, to) { var args = [from > to ? to : to - count, 0]; args.push.apply(args, list.splice(from, count)); list.splice.apply(list, args); return list; } 

Comments

1

I came here looking for a rearranging complete array, I want something like I did below, but found most of the answers for moving only one element from position A to position B.

Hope my answer will help someone here

function reArrangeArray(firstIndex=0,arr){ var a = []; var b = [] for(let i = 0; i<= (arr.length-1); i++){ if(i<firstIndex){ a.push(arr[i]) }else{ b.push(arr[i]) } } return b.concat(a) } const arrayToRearrange = [{name: 'A'},{name: 'B'},{name: 'C'},{name: 'D'},{name: 'E'}]; reArrangeArray(2,arrayToRearrange) // Output // [ // { name: 'C' }, // { name: 'D' }, // { name: 'E' }, // { name: 'A' }, // { name: 'B' } // ] 

Comments

0

As a simple mutable solution you can call splice twice in a row:

playlist.splice(playlist.length - 1, 1, ...playlist.splice(INDEX_TO_MOVE, 1)) 

On the other hand, a simple inmutable solution could use slice since this method returns a copy of a section from the original array without changing it:

const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)] 

Comments

-3

Reorder its work This Way

 var tmpOrder = playlist[oldIndex]; playlist.splice(oldIndex, 1); playlist.splice(newIndex, 0, tmpOrder); 

I hope this will work

1 Comment

What does this add over the existing answers?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.