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.
As the references are stored in a array, it makes sense to preserve the order.
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.
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.
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 });
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With