0

I'm sorting a list of <li> elements. I adapted a function on a page that I can't link right now. You can see the live site here. Click on "Sort and Filter" and click any of the Sort by methods (English name, material, status...). All sorts are essentially the same, so CPU time is the same.

My jQuery function looks like this:

jQuery.fn.sort = function() {
    return this.pushStack([].sort.apply(this, arguments), []);
};
  function sortAscending1(a, b)  { return $(a).find(".english").text() > $(b).find(".english").text() ? 1 : -1; };  
  function sortDescending1(a, b)  { return $(a).find(".english").text() < $(b).find(".english").text() ? 1 : -1; };

And I'm calling it from the following jQuery line (s_alf_eng is a clicable div on the page).

$(document).ready(function() {
    $(".s_alf_eng").toggle(
        function() {
            $('.media-status-specie li').sort(sortAscending1).appendTo('.media-status-
        },
        function() {
            $('.media-status-specie li').sort(sortDescending1).appendTo('.media-status-specie');
        }); 

I can provide any extra clarification quickly. Thanks!

EDIT: The question is that executing this sort for large list takes several seconds. In my core2duo it might take up to 20 seconds! I changed the find(".english") to filter(".english") and the speed seems to be the same. Any idea on how to speed that up?

3
  • What's the question? Code uses JavaScript native sorting algorithm which I believe almost always is quick sort. Commented Oct 7, 2009 at 11:58
  • Sorry, I forgot to add it!! This is the largest list (family), and the slowest of course: ibc.lynxeds.com/family/tyrant-flycatchers-tyrannidae Commented Oct 7, 2009 at 12:01
  • Opera shows a message to let you know the sort is in progress, but FF, IE, etc only shows the message when the sort is done. That's a related question here: stackoverflow.com/questions/1531064 Commented Oct 7, 2009 at 12:09

2 Answers 2

2

Make a copy in memory of the list and sort it, then replace the existing list with the sorted one. That would be faster than manipulating live, visible, DOM elements.

Sign up to request clarification or add additional context in comments.

8 Comments

You mean like having the list 4 or 5 times (one for each sort) and just switch the display of them? That could be an option, but I wonder if it would make the page much heavier.
I use this technique on the list of up to 500ish business listings at keytosavannah.com/listings/browse/category/things_to_do. Javascript is minified but basically I push the data into an array on page load and print it to the results div as needed by the pagination. The downside to this method is that you have nothing to show the search engine spiders unless you make other arrangements.
No, not create a copy for each sort. Create the copy on the fly, when the sort is required. Or, create on single copy in memory and use it whenever a sort is needed. That would cause complications, though, if the list can change dynamically.
I think I get the point. What I'm doing now is sorting the visible elements. Thus, sorting by a, then by b, then by a, then by b... requires always the same time. Creating a copy on the fly, and then (once sorted) hide the original and show the newly created one. Switching between sort a, sort b, sort a.. would be as fast as hiding a div containing all <li> elements. That's the point?
It would be faster, because there would not be the added overhead of the browser updating the visible page on each iteration of the sort. The price is the memory used to hold the copy. Note - you would delete the old list and insert the new one in its place, not just hide the old list (unless it is already in an order that is optimized for your sort algorithm).
|
1

I think if you add name as metadata to the node and eliminate looking through the DOM on every comparison, it'll be much faster. Remember, there's O(n2) of them after all.

$(function() { 
    $('.media-status-specie li')
        .each(function () {
            $(this).data('name', $(this).find(".english").text());
        })
});

.... 

function sortDescending1(a, b)  { 
    return $(a).data('name') < $(b).data('name') ? 1 : -1; 
}

Disclaimer: It's my opinion, I'm no good at guessing slow points as any other developer out there, use profiler to find real performance killer.

4 Comments

This is much faster! I have 5 different sorts (10 functions). I think I can parse all the list and fill more variables like: .each(function () { $(this).data('english', $(this).find(".english").text()); $(this).data('scientific', $(this).find(".scientific").text()); $(this).data('total', $(this).find(".total-material").text()); }) Is this going to increase the memory of the page? The largest page is below 500 <li> elements.
Sure it will increase the memory consumption. Not really sure if it would be a problem though and it will heavily depend on the browser. You'd have to run few experiments to find out.
BTW you can assign value of any type, so data('sorting params', {english: 'name', scientific: 'bird'}) will work too.
It's already on the live site! It's performing much better. It even works good on IE6 :) Many thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.