How can you sort an array without mutating the original array?

JavascriptArraysSorting

Javascript Problem Overview


Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this

function sort(arr) {
  return arr.sort();
}

and I tested it with this, which shows that my sort method is mutating the array.

var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a);  //alerts "1,2,3,3,3,4,5,7,7"

I also tried this approach

function sort(arr) {
  return Array.prototype.sort(arr);
}

but it doesn't work at all.

Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?

Javascript Solutions


Solution 1 - Javascript

You need to copy the array before you sort it. One way with es6:

const sorted = [...arr].sort();

The spread-syntax as array literal (copied from mdn):

var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

Solution 2 - Javascript

Just copy the array. There are many ways to do that:

function sort(arr) {
  return arr.concat().sort();
}

// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects

Solution 3 - Javascript

Try the following

function sortCopy(arr) { 
  return arr.slice(0).sort();
}

The slice(0) expression creates a copy of the array starting at element 0.

Solution 4 - Javascript

You can use slice with no arguments to copy an array:

var foo,
    bar;
foo = [3,1,2];
bar = foo.slice().sort();

Solution 5 - Javascript

You can also do this

d = [20, 30, 10]
e = Array.from(d)
e.sort()

This way d will not get mutated.

function sorted(arr) {
  temp = Array.from(arr)
  return temp.sort()
}

//Use it like this
x = [20, 10, 100]
console.log(sorted(x))

Solution 6 - Javascript

Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:

let arrCopy = JSON.parse(JSON.stringify(arr))

Then you can sort arrCopy without changing arr.

arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)

Please note: this can be slow for very large arrays.

Solution 7 - Javascript

Try this to sort the numbers. This does not mutate the original array.

function sort(arr) {
  return arr.slice(0).sort((a,b) => a-b);
}

Solution 8 - Javascript

There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.

For example:

const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]

As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.

Solution 9 - Javascript

I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.

I can propose yet another approach with a native function which returns a sorted array.

This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.

// Remember that it is not recommended to extend build-in prototypes 
// or even worse override native functions.  
// You can create a seperate function if you like

// You can specify any name instead of "sorted" (Python-like)

// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
  // If it does not exist you provide your own method
  Array.prototype.sorted = function () {
    Array.prototype.sort.apply(this, arguments);
    return this;
  };
}

This way of solving the problem was ideal in my situation.

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
QuestionPeter OlsonView Question on Stackoverflow
Solution 1 - JavascriptPutzi SanView Answer on Stackoverflow
Solution 2 - JavascriptRob WView Answer on Stackoverflow
Solution 3 - JavascriptJaredParView Answer on Stackoverflow
Solution 4 - JavascriptzzzzBovView Answer on Stackoverflow
Solution 5 - JavascriptAditya AgarwalView Answer on Stackoverflow
Solution 6 - JavascriptHamadaView Answer on Stackoverflow
Solution 7 - JavascriptPratiView Answer on Stackoverflow
Solution 8 - JavascriptJoshView Answer on Stackoverflow
Solution 9 - JavascriptOleh DzobaView Answer on Stackoverflow