81

I have an array of objects. I want to move a selected object to the last position in the array. How do I do this in javascript or jquery?

Here is some code I have:

var sortedProductRow = this.product_row;

for (var s in sortedProductRow) {
    if (sortedProductRow[s]["parent_product_type"] != "")
        // Move this object to last position in the array
}

I'm looping through this with a for loop, and I want the output to be ordered so that all objects that does not have a "parent_product_type" value comes first, then those with a value.

Paul
  • 770
  • 1
  • 7
  • 12
Johan Dahl
  • 1,672
  • 3
  • 19
  • 35
  • 2
    An **object** is not an **array** and position is meaninglessness, it's only keys and values. read more - http://stackoverflow.com/q/5525795/104380 – vsync Jul 23 '14 at 11:36
  • who says `sortedProductRow` is an object? you can iterate an array with for in as well (I don't say it's a good idea, but it's possible) – Ferdi265 Jul 23 '14 at 11:40
  • 1
    Hmm ok, then I'm not sure what I need to do. I can loop through this array with a for loop, and the objects come out in the order that they appear within the "array" (or object). So what do I need to do if I want to change the order that they come out of the for loop? – Johan Dahl Jul 23 '14 at 11:41

8 Answers8

151

to move an element (of which you know the index) to the end of an array, do this:

array.push(array.splice(index, 1)[0]);

If you don't have the index, and only the element, then do this:

array.push(array.splice(array.indexOf(element), 1)[0]);

Example:

    var arr = [1, 2, 6, 3, 4, 5];
    arr.push(arr.splice(arr.indexOf(6), 1)[0]);
    console.log(arr); // [1, 2, 3, 4, 5, 6]

NOTE:

this only works with Arrays (created with the [ ... ] syntax or Array()) not with Objects (created with the { ... } syntax or Object())

Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75
Ferdi265
  • 2,879
  • 1
  • 17
  • 15
  • 3
    needs some more explanation. Although this solves the problem, no one is learning anything. – Devashish Jul 08 '19 at 09:52
  • 1
    hi @Ferdi265 could you please explain why u have added [0] after array.splice method. Thanks in advance – vandu May 04 '20 at 11:27
  • 6
    `Array.splice()` returns an array containing all of the removed elements, so in this case, `[6]`. We only want to push `6` to the end of the array, so we take the first element of that array. If you don't add the `[0]`, you will get `[1, 2, 3, 4, 5, [6]]` instead – Ferdi265 May 04 '20 at 17:41
  • So to move an element to a specific index, we do: `arr.splice(index, 0, arr.splice(arr.indexOf(6), 1)[0]);` – HDKT Oct 23 '20 at 12:49
  • Maybe we can also do something like: `Array.prototype.move = function(element, index) { arr.splice(index, 0, arr.splice(arr.indexOf(element), 1)[0]); }` – HDKT Oct 23 '20 at 12:59
  • @HDKT In 2020 and beyond? No. You need a *really* good reason to touch `Array.prototype`. – targumon Aug 17 '21 at 13:17
18

Moving the first element of an array to the end of the same array

    var a = [5,1,2,3,4];
    a.push(a.shift());
    console.log(a); // [1,2,3,4,5]

or this way

    var a = [5,1,2,3,4];
    var b = a.shift();
    a[a.length] = b;
    console.log(a); // [1,2,3,4,5]

Moving any element of an array to any position in the same array

    // move element '5' (index = 2) to the end (index = 4)
    var a = [1, 2, 5, 4, 3];
    a.splice(4,0,a.splice(2,1)[0]);
    console.log(a); // [1, 2, 4, 3, 5]

or it could be converted to a prototype as well, like this where x represents the current position of element while y represents the new position in array

var a = [1, 2, 5, 4, 3];
Array.prototype.move = function(x, y){
      this.splice(y, 0, this.splice(x, 1)[0]);
      return this;
    };
    
    a.move(2,4);
    console.log(a); // ["1", "2", "4", "3", "5"]

Answer to the @jkalandarov comment

function moveToTheEnd(arr, word){
  arr.map((elem, index) => {
    if(elem.toLowerCase() === word.toLowerCase()){
      arr.splice(index, 1);
      arr.push(elem);
    }
  })
  return arr;
}
console.log(moveToTheEnd(["Banana", "Orange", "Apple", "Mango", "Lemon"],"Orange"));
hex494D49
  • 9,109
  • 3
  • 38
  • 47
  • Elegant solution, but this can only move the first element of the array to the end. – Ferdi265 Jul 23 '14 at 11:49
  • @Ferdi265 I don't know why I was sure that the OP wants to move the first element :) – hex494D49 Jul 23 '14 at 11:50
  • Thanks but it's not the first element I want to move. I'm looping through the sortedProductRow array/object(?) and when I find a property name "parent_product_type" that has a value, I want to move it to the last position in the array. This way, my array will have only objects without a value for the property "parent_product_type" coming first, then all objects with a value for this property. – Johan Dahl Jul 23 '14 at 11:55
  • 1
    @JohanDahl Sorry :) I updated the answer to something more useful :) so give it a try. – hex494D49 Jul 23 '14 at 12:08
  • Thanks for your answer! I ended up using Ferdi's second method which worked well. – Johan Dahl Jul 23 '14 at 12:30
  • What if I want to move the elements that repeat several times in an array to the end of the array? Lets say, I want to move all 'b's to the end of an array? – jkalandarov May 12 '20 at 16:34
  • 1
    For those who want to return the element that's being moved to the end of the array: `const output = a[a.push(a.shift())-1];` – JacobF Mar 23 '23 at 10:01
10

Immutable way:

const changedArr = [...prevArr.filter(a => a !== element), element]
Nagibaba
  • 4,218
  • 1
  • 35
  • 43
9

This is more clean, without using the array index of [0]

const colors = ['white', 'black', 'red', 'blue', 'green'];

// will push the blue to the end of the array
colors.push(colors.splice(colors.indexOf('blue'), 1).pop());

console.debug(colors);
// ["white", "black", "red", "green", "blue"]
Medo
  • 418
  • 7
  • 11
5

Using an anonymous function you can pass in the array and the value to filter by.

let concatToEnd = function (arr, val) {
        return arr.filter(function(x) {
            return x !== val; // filter items not equal to value
        }).concat(arr.filter(function(x) { // concatonate to filtered array
            return x === val; // filter items equal to value 
        })
    );
}

// invoke
concatToEnd(array, 'parent_product_type');

You could probably shorten this further:

let concatToEnd = (arr,val) => arr.filter(x => x !== val).concat(arr.filter(x => x === val))

This function filters the items which do not equal the value passed in, then concatenates the result (to the end of the filtered array) of another filter function which filters out the items which do equal the value you've passed in.

This function essentially separates the array into 2 filtered parts and then concatenates them back together

This hasn't been tested for your use-case, but I've used something similar to move all numbers of an array to the end of the index.

UncaughtTypeError
  • 8,226
  • 4
  • 23
  • 38
1

Move any element to last position - for lodash users:

    const array = ['A', 'B', 'C', 'D'] // output: A, B, C, D

// finds index of value 'B' and removes it
    _.pull(array , 'B') // output: A, C, D

// adds value of 'B' to last position
    _.concat(array , 'B') // output: A, C, D, B
Advem
  • 21
  • 2
0

You can move any number of items by splicing them, then spreading them into a push.

const numberOfItems = 3;
let items = [1,2,3,4,5,6,7,8,9];
items.push(...items.splice(0, itemsToMove))
Djave
  • 8,595
  • 8
  • 70
  • 124
0

Moving all items equal so something to the end can also be done by concat.

const myArray = [1, 0, 3, 5, 0, 'a', 3, 's']
    
const moveZerosToEnd = (arr) => {
   return arr.filter(item => item !== 0).concat(arr.filter(item => item === 0))
}

console.log(myArray)                 // [1, 0, 3, 5, 0, 'a', 3, 's']
console.log(moveZerosToEnd(myArray)) // [1, 3, 5, 'a', 3, 's', 0, 0] 
Abeldlp
  • 89
  • 5