#1
  1. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144

    Secondary sorting an object


    Hi--

    I'm trying to sort a list of films first by day, then by title and it works everywhere *except* Chrome.

    I'll have something like this for data:
    Code:
    [{
       "filmtitle":"100 Years: One Woman's Fight for Justice",
       "sortabletitle":"100 Years",
       "filmyear":"2016",
       "filmshowtime":"2017-10-30 12:00:00"
       },
       "filmtitle":"Iron Maiden Flight 666",
       "sortabletitle":"Iron Maiden",
       "filmyear":"2017",
       "filmshowtime":"2017-10-30 12:00:00"
       },
       "filmtitle":"Futurama",
       "sortabletitle":"Futurama",
       "filmyear":"2017",
       "filmshowtime":"2017-10-29 12:00:00"
       },
    ...
    ]
    I'm allowing my users to choose how they sort films. When they sort by title, "100 Years..." Should be first. When they sort by day, it should be Futurama, 100 Years, Iron Maiden.

    Here's how I'm sorting:

    Code:
    cmp = function(x, y) {
    				return x > y ? 1 : x < y ? -1 : 0; 
    			};
    			
    			filmdata.sort(function(a, b) {
    				//note the minus before -cmp, for descending order
    				return cmp( 
    			        [cmp(a.filmshowtime, b.filmshowtime), cmp(a.filmtitle, b.filmtitle)], 
    			        [cmp(b.filmshowtime, a.filmshowtime), cmp(b.filmtitle, a.filmtitle)]
    			    );
    			});

    As I said, this works everywhere except Chrome. Stupid IE even does this right. Any ideas?

    Thank you!
    Last edited by Frank Grimes; September 25th, 2017 at 02:47 PM.
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  2. #2
  3. Maddening Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    16,453
    Rep Power
    9645
    Your comparison function is completely messed up. Arrays? Comparing the same properties in both directions? It's all a big WTF.

    Comparisons are easy:
    javascript Code:
    filmdata.sort(function(a, b) {
    	// desc number comparison: b.property - a.property
    	// desc string comparison: b.property.localeCompare(a.property)
    	var cmp = /* comparison of .filmshowtime, not sure if number or string */;
    	if (cmp != 0) {
    		return cmp;
    	}
     
    	cmp = /* comparison of .filmtitle, surely string */;
    	if (cmp != 0) {
    		return cmp;
    	}
     
    	return 0;
    });

    1. Compare the first pair of properties. If they don't match then that's the answer.
    2. Compare the second pair of properties. If they don't match then that's the answer.
    3. Repeat for all the other pairs of properties. (You only have the two.)
    4. If every pair matched then the result is equality.

    The last comparison could be simply "return <comparison>;" but I didn't do that to demonstrate how the system works.
  4. #3
  5. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    Originally Posted by requinix
    Your comparison function is completely messed up. Arrays? Comparing the same properties in both directions? It's all a big WTF.

    Comparisons are easy:
    javascript Code:
    filmdata.sort(function(a, b) {
    	// desc number comparison: b.property - a.property
    	// desc string comparison: b.property.localeCompare(a.property)
    	var cmp = /* comparison of .filmshowtime, not sure if number or string */;
    	if (cmp != 0) {
    		return cmp;
    	}
     
    	cmp = /* comparison of .filmtitle, surely string */;
    	if (cmp != 0) {
    		return cmp;
    	}
     
    	return 0;
    });

    1. Compare the first pair of properties. If they don't match then that's the answer.
    2. Compare the second pair of properties. If they don't match then that's the answer.
    3. Repeat for all the other pairs of properties. (You only have the two.)
    4. If every pair matched then the result is equality.

    The last comparison could be simply "return <comparison>;" but I didn't do that to demonstrate how the system works.


    Thank you for this. I haven't done many comparisons in JS like this so I'm out of my element. My filmshowtime is a Unix timestamp for easy comparisons.

    I'll have another stab at this and see what happens even though I've totally lost interest in this. This is a project that will remain online for a couple of days and be seen by fewer than 100 people and I'm not liking the client so much these days.

    Any tips for winning the lottery?
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  6. #4
  7. Maddening Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    16,453
    Rep Power
    9645
    Math. Calculate expected winnings according to odds: sometimes there are circumstances where you can "expect" (odds are better than 50/50) to win more money than you have to spend in tickets. Thing is it's not often, not always knowable, and does require buying a fair number of tickets to make it worthwhile.

    Or you can just pick 4 8 15 16 23 42 every time.
  8. #5
  9. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    Man, I have no idea what I'm doing wrong here:

    javascript Code:
    filmdata.sort(function(a, b) {
     
    				cmp=a.unix > b.unix;
     
    				if (cmp != 0) {
    					return cmp;
    				}
     
    				cmp = a.sortabletitle > b.sortabletitle;
     
    				if (cmp != 0) {
    					return cmp;
    				}
     
    				return 0;
    			});


    Again, this works fine in all browsers EXCEPT Chrome.
    Last edited by Frank Grimes; September 26th, 2017 at 01:31 PM.
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  10. #6
  11. Wiser? Not exactly.
    Devshed God 2nd Plane (6000 - 6499 posts)

    Join Date
    May 2001
    Location
    Bonita Springs, FL
    Posts
    6,124
    Rep Power
    4103
    Your comparison function needs to return a value less than 0 if a < b, a value greater than 0 if a > b, or 0 if they are equal.

    For numbers, you can use subtraction to get the appropriate return value.
    Code:
    var cmp = a.unix - b.unix;
    if (cmp !== 0){
        return cmp;
    }
    For strings you need to do your comparison and assign an appropriate result. Simply assigning the result of the comparison operation won't work because that is a simple true/false value.
    Code:
    if (a.sortabletitle < b.sortabletitle){
        cmp = -1;
    } else if (a.sortabletitle > b.sortabletitle){
        cmp = 1;
    } else {
       cmp = 0;
    }
    
    return cmp;
    Info and examples

    Comments on this post

    • Frank Grimes agrees
    Last edited by kicken; September 26th, 2017 at 02:48 PM.
    Recycle your old CD's



    If I helped you out, show some love with some reputation, or tip with Bitcoins to 1N645HfYf63UbcvxajLKiSKpYHAq2Zxud
  12. #7
  13. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    Originally Posted by kicken
    Your comparison function needs to return a value less than 0 if a < b, a value greater than 0 if a > b, or 0 if they are equal.

    For numbers, you can use subtraction to get the appropriate return value.
    Code:
    var cmp = a.unix - b.unix;
    if (cmp !== 0){
        return cmp;
    }
    For strings you need to do your comparison and assign an appropriate result. Simply assigning the result of the comparison operation won't work because that is a simple true/false value.
    Code:
    if (a.sortabletitle < b.sortabletitle){
        cmp = -1;
    } else if (a.sortabletitle > b.sortabletitle){
        cmp = 1;
    } else {
       cmp = 0;
    }
    
    return cmp;
    Info and examples
    Thank you. This works and I appreciate the explanation and links.
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  14. #8
  15. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    So here's a funny thing.

    My sorting works fine in all browsers. I am calling a function to sort the object and in that same function I send the list of film titles to the console. It looks fine in FF and Chrome.

    What's funny is I'm using another function to build the HTML from the object and send it to the DOM. However, when I send the list of film titles to the console in that second function, it again looks fine in FF, but in Chrome it changes the order.

    Seriously..WTF?
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  16. #9
  17. Wiser? Not exactly.
    Devshed God 2nd Plane (6000 - 6499 posts)

    Join Date
    May 2001
    Location
    Bonita Springs, FL
    Posts
    6,124
    Rep Power
    4103
    You'll have to post more of your code. A jsfiddle that replicates the issue would be great.
    Recycle your old CD's



    If I helped you out, show some love with some reputation, or tip with Bitcoins to 1N645HfYf63UbcvxajLKiSKpYHAq2Zxud
  18. #10
  19. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    I won't be able to create a jsfiddle with this since my data is coming from a database, but here is my code:

    javascript Code:
     
     
    sortday();
    displayday();
     
    function sortday() {
    function sortDay() {
     
    function sortday() {
     
    	filmdata.sort(function(a, b) {			
    		var cmp=a.unix - b.unix;
     
    		if (cmp != 0) {
    			return cmp;
    		}
     
    		if (a.sortabletitle < b.sortabletitle){
    			cmp = -1;
    		} else if (a.sortabletitle > b.sortabletitle){
    			cmp = 1;
    		} else {
    			cmp = 0;
    		}
     
    		return cmp;
    	});
     
    	$.each(filmdata,function(i,obj) {
    			console.log(obj.filmtitle);
    	});
    };
     
     
    function displayday() {
    	$.each(filmdata,function(i,obj) {
    			console.log(obj.filmtitle);
    	});
    }


    Seriously. That's all I'm doing. Chrome is changing sort order in the displayday() function.
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence
  20. #11
  21. Plays with fire
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Aug 2003
    Location
    Barsoom
    Posts
    1,146
    Rep Power
    144
    Okay, never mind about this. I've given up trying to make this work. There's a bug in Chrome that's hosing this up for me and I've run out of time and patience. The client just needs to deal with this.

    Thanks everyone for your help.
    “Be ashamed to die until you have won some victory for humanity.” -- Horace Mann

    "...all men are created equal." -- US Declaration of Independence

IMN logo majestic logo threadwatch logo seochat tools logo