I'm looking to sort an array of about 200-300 objects, sorting on a specific key and a given order (asc/desc). The order of results must be consistent and stable.
What would be the best algorithm to use, and could you provide an example of it's implementation in javascript?
Thanks!
On the other hand, being one of the fastest quadratic sorting algorithms, Insertion Sort usually outperforms Bubble Sort, Gnome Sort and Selection Sort. In addition to that, when our input array size is very small (10-20 elements), Insertion Sort can even outperform Quicksort and Merge Sort.
But since it has the upper hand in the average cases for most inputs, Quicksort is generally considered the “fastest” sorting algorithm.
JavaScript by default uses insertion sort for the sort() method. This means that it is not appropriate when sorting large data sets. When dealing with large data sets, one should consider other sorting algorithms such as merge sort.
All major JavaScript engines now implement a stable Array#sort . It's just one less thing to worry about as a JavaScript developer. Nice! (Oh, and we did the same thing for TypedArray s: that sort is now stable as well.)
It is possible to get a stable sorting from a non-stable sort function.
Before sorting you get the position of all the elements. In your sort condition, if both elements are equal, then you sort by the position.
Tada! You've got a stable sort.
I've written an article about it on my blog if you want to know more about this technique and how to implement it: http://blog.vjeux.com/2010/javascript/javascript-sorting-table.html
Since you are looking for something stable, the merge sort should do.
http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
The code can be found at the above website:
function mergeSort(arr)
{
if (arr.length < 2)
return arr;
var middle = parseInt(arr.length / 2);
var left = arr.slice(0, middle);
var right = arr.slice(middle, arr.length);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right)
{
var result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length)
result.push(left.shift());
while (right.length)
result.push(right.shift());
return result;
}
EDIT:
According to this post, it looks like Array.Sort in some implementations uses a merge sort.
Somewhat shorter version of the same thing using ES2017 features like arrow functions and destructuring:
var stableSort = (arr, compare) => arr
.map((item, index) => ({item, index}))
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
.map(({item}) => item)
It accepts input array and compare function:
stableSort([5,6,3,2,1], (a, b) => a - b)
It also returns new array instead of making in-place sort like the built-in Array.sort() function.
If we take the following input
array, initially sorted by weight
:
// sorted by weight
var input = [
{ height: 100, weight: 80 },
{ height: 90, weight: 90 },
{ height: 70, weight: 95 },
{ height: 100, weight: 100 },
{ height: 80, weight: 110 },
{ height: 110, weight: 115 },
{ height: 100, weight: 120 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 100, weight: 135 },
{ height: 75, weight: 140 },
{ height: 70, weight: 140 }
]
Then sort it by height
using stableSort
:
stableSort(input, (a, b) => a.height - b.height)
Results in:
// Items with the same height are still sorted by weight
// which means they preserved their relative order.
var stable = [
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 70, weight: 140 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 80 },
{ height: 100, weight: 100 },
{ height: 100, weight: 120 },
{ height: 100, weight: 135 },
{ height: 110, weight: 115 }
]
However sorting the same input
array using the built-in Array.sort()
(in Chrome/NodeJS):
input.sort((a, b) => a.height - b.height)
Returns:
var unstable = [
{ height: 70, weight: 140 },
{ height: 70, weight: 95 },
{ height: 70, weight: 125 },
{ height: 70, weight: 130 },
{ height: 75, weight: 140 },
{ height: 80, weight: 110 },
{ height: 90, weight: 90 },
{ height: 100, weight: 100 },
{ height: 100, weight: 80 },
{ height: 100, weight: 135 },
{ height: 100, weight: 120 },
{ height: 110, weight: 115 }
]
Array.prototype.sort
is now stable in V8 v7.0 / Chrome 70!Previously, V8 used an unstable QuickSort for arrays with more than 10 elements. Now, we use the stable TimSort algorithm.
source
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