Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array items and preserve order of same elements

Suppose I have this array:

var array = [   { name: "border-color", value: "#CCCCCC" },   { name: "color", value: "#FFFFFF" },   { name: "background-color", value: "rgb(0, 0, 0)" },   { name: "background-color", value: "rgba(0, 0, 0, .5)" } ]; 

And this function to sort the array by name:

array.sort(function(a, b) {   if (a.name < b.name) return -1;   if (a.name > b.name) return 1;   return 0; }); 

And ECMAScript language specifications that tell me that:

The sort is not necessarily stable (that is, elements that compare equal do not necessarily remain in their original order).

So, after sorting, the two items with name = background color could appear in any order i.e.:

[   { name: "background-color", value: "rgb(0, 0, 0)" },   { name: "background-color", value: "rgba(0, 0, 0, .5)" },   ... ] 

Or

[   { name: "background-color", value: "rgba(0, 0, 0, .5)" },   { name: "background-color", value: "rgb(0, 0, 0)" },   ... ] 

How can I sort the array so that items with same name maintain their relative order? I would rather not hardcode anything.

like image 243
Salman A Avatar asked Jul 03 '15 20:07

Salman A


People also ask

Does array preserve order?

As the references are stored in a array, it makes sense to preserve the order.

What is a correct method to sort the elements of an array?

The sort() method allows you to sort elements of an array in place. Besides returning the sorted array, the sort() method changes the positions of the elements in the original array. By default, the sort() method sorts the array elements in ascending order with the smallest value first and largest value last.

Does JavaScript list preserve order?

However, JavaScript objects have one fatal flaw: they're not properly iterable, in the sense of preserving “insertion order.” In other words, objects don't remember the order that object keys were added in.


Video Answer


2 Answers

Theoretically before sorting you could keep track of its index in the array and take that into account when sorting.

var sortArray = yourarray.map(function(data, idx){     return {idx:idx, data:data} })  sortArray.sort(function(a, b) {   if (a.data.name < b.data.name) return -1;   if (a.data.name > b.data.name) return 1;   return a.idx - b.idx });  var answer = sortArray.map(function(val){     return val.data }); 
like image 113
noveyak Avatar answered Oct 03 '22 19:10

noveyak


This changed as of ES2019, Array#sort is stable, meaning that the two entries with the same name will have the same position relative to one another as they did before the array was sorted:

22.1.3.27 Array.prototype.sort ( comparefn )

The elements of this array are sorted. The sort must be stable (that is, elements that compare equal must remain in their original order).

(my emphasis)

So in your case, the order of { name: "background-color", value: "rgb(0, 0, 0)" } and { name: "background-color", value: "rgba(0, 0, 0, .5)" } will remain the same, because they compare as equal.

Prior to ES2019, the sort wasn't required to be stable, so they could have had their order reversed — or not, depending on the implementation.

Stable sort is broadly supported (not least because most engines already implemented a stable sort, so there was nothing for them to do).

like image 27
T.J. Crowder Avatar answered Oct 03 '22 20:10

T.J. Crowder