views:

1020

answers:

5

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!

+6  A: 

Since you are looking for something stable, the merge sort should do.

http://en.literateprograms.org/Merge_sort_(JavaScript)

EDIT:

According to this post, it looks like Array.Sort in some implementations uses a merge sort.

Kevin
++ Merge sort is my favorite. It's simple and stable with no bad worst cases.
Mike Dunlavey
I'll look into this. Thanks!
Bill Casarin
+1  A: 

Will the built in sort function do? http://www.w3schools.com/jsref/jsref%5Fsort.asp

finalman
I don't think the built-in sort uses a stable algorithm
Philippe Leybaert
I was thinking the same thing.
Kevin
Oh, bummer. I second the suggested merge sort then :)
finalman
Good point. It's not guaranteed, but browsers have moved toward using stable implementations. IE 6+ is stable. Firefox 3 is. Safari is. Not sure about Chrome (I'd hope it is). Or Opera (it used to be unstable--I hope it's fixed now).
Nosredna
Chrome not stable. Does anyone know if Opera 10 is?
Nosredna
+1  A: 

Check this article:

http://www.hedgerwow.com/360/dhtml/js%5Farray%5Fstable%5Fsort.html

It seems that only FF 2.0 and Opera 9 and earlier have a non-stable sort implementation. All other mainstream browsers do.

Philippe Leybaert
Yikes. I just tried Chrome and it doesn't look stable, so I'd say _assuming_ stable in modern browsers is a big mistake.
Nosredna
That's why I was cautious and said "it seems" :-) Anyhow, I wouldn't rely on it.
Philippe Leybaert
A: 

You should be able to utilize the core Array.sort method. Example...

var data = []; //populate array

function sortByName(a, b) {
  var x = a.LastName.toLowerCase();
  var y = b.LastName.toLowerCase();
  return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

data.sort(sortByName);

Note: this only sorts ascending. But you can take care of that by tweaking the function or using Array.reverse.

Josh Stodola
Note that the built-in array sort is not stable in (at least) Chrome, so it violates one of your requirements.
Nosredna
Please elaborate on the "not stable". I would have to say it is feasible to rely on the core Javascript framework.
Josh Stodola
The question specifically asked for a stable sort, but the built-in array sort is not required to be stable (according to the ECMA standard).
Philippe Leybaert
"not stable" means that sorting a sorted array could change the order of the elements
Philippe Leybaert
I wasn't aware that it was instable in chrome, this is definitely a big requirement for me. No Array.sort() for me!
Bill Casarin
The only thing I think webkit screws up on (based on my experience) is when the sort function returns a Boolean instead of integer, which as you can see I have addressed here.
Josh Stodola
And where's the documentation that says "Javascript 1.2 has a sort function, but it does not require a stable browser implementation"?
Josh Stodola
When I say stable I mean "stable sort". Which means it returns the array in a consistent ordering. I tried quicksort initially, but when I was resorting by asc/desc they would appear in different order every time.
Bill Casarin
Chrome fails this test on my XP machine: http://www.hedgerwow.com/360/dhtml/js_array_stable_sort.html I have 3.0.195.21 (the up-to-date beta as of now).
Nosredna
Can anyone else verify Chrome's instable results (in either the mainline or beta track)? I'd like to report that as a bug, since everyone else seems to be going stable.
Nosredna
I'm on the chrome dev channel and I'm getting non stable sort results. If there's not a bug report yet I'd definitely add one.
Bill Casarin
Well, I've used this method for years, and I for one am not going to change simply because Google does not properly implement it. But that's just me! I don't like to get bothered by things I can not control.
Josh Stodola
ECMAScript Language Specification 3rd Edition section 15.4.4.11: "The elements of this array are sorted. **The sort is not necessarily stable** (that is, elements that compare equal do not necessarily remain in their original order)." So Google's implementation is to spec, *not* a bug. https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/sort also notes that although Mozilla's current implementation is stable, "the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this."
NickFitz
Agree that Google's implementation is not a bug. However, it's in their best interest to match what the other browsers are doing, as they did with returning objects in the order they were added instead of an arbitrary order (as the spec allows). @Josh, if you've used this method for years, your results were different for users of FF2 than they were for IE users. I'm guessing that you didn't need a stable sort. Whether you need one depends on the situation.
Nosredna
Thanks for doing the leg work guys! I am thinking about porting my .NET QuickSort implementation over to JavaScript. Wonder how it will perform.
Josh Stodola
@Josh--Maybe your sort could fall back to the native sort if you detect that the native sort is stable. Just an idea.
Nosredna
+2  A: 

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

Vjeux