SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Guru mwolfe's Avatar
    Join Date
    Mar 2005
    Posts
    912
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    accessing class information inside custom compare function in sort

    alright so i've got a google maps application that maps real estate listings. I want to be able to sort the listings with an icon based on color. Now i know most of how to do this, but the sorting is causing me trouble. Here is the basic structure of

    Code:
    function RealEstateMap() {
     this.listings = new HashTable();
    
     this.getListings = function () {
     // this is a basic implementation in pseudocode, the real app is more complex:
        //use ajax to get an array of new listings that are on the map shown 
        // merge them into the hash table
        //create an array of hash table keys, call it this.listingKeys
        //sort the array based on what the user has selected
       // place the icons on the map
     }
    
    //register getListings to be called when the map is moved
    }
    the hastable is basically the same implementation is this:
    http://weblogs.asp.net/ssadasivuni/a.../17/27902.aspx
    which is pretty simple.


    Now, i can't really sort a hashtable, however I can sort its keys.
    So then if i've got the hashtable and an array of keys, say the variable is named listingKeys, i just do listingKeys.sort();
    however, I want to sort based on properties of the original object, since this is a real estate application.

    So then i can create my own sorters that take in a the listing id and look up that listing in the hashtable, and then do the comparison.
    However, i can't figure out how to get a reference to the hashtable from within the comparison function..

    so this is what i'm currently trying to do inside the above class

    Code:
    	this.sortListings = function() {
    
    		
    
    		switch (this.sortBy) {
    			case "price-per-sq-ft" :
    				comparator = this.compareByPriceSquareFeet;
    				break;
    			case "bedrooms" :
    				comparator = this.compareByBedrooms;
    				break;
    			case "bathrooms" :
    				comparator = this.compareByBathrooms;
    				break;
    		}
    		
    		this.sortedListings.sort(comparator);
    
    
    
    	}

    where for example the this.compareByBedrooms is simply a function like
    Code:
    this.compareByBedrooms = function(mlsId1, mlsId2) {
    		var listing1 = this.listings.getItem(mlsId1);
    		var listing2 = this.listings.getItem(mlsId2);
    		return listing1.bedrooms - listing2.bedrooms
    	}
    however, in the compareByBedrooms there is no this.listings in that context so it gives an error. How can i get a reference to that, any ideas?

  2. #2
    SitePoint Guru mwolfe's Avatar
    Join Date
    Mar 2005
    Posts
    912
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    alright well i figured out how to do it, i just put the compare functions (as normal functions inside the sort function as follows
    Code:
    this.sortListings = function() {
            listings = this.listings;
            function compareByPrice(mlsId1, mlsId2) {
                var listing1 = listings.getItem(mlsId1);
                var listing2 = listings.getItem(mlsId2);
                return compareByIntColSortAsc(listing1.listingPrice, listing2.listingPrice);
            }
    
            function(mlsId1, mlsId2) {
                var listing1 = listings.getItem(mlsId1);
                var listing2 = listings.getItem(mlsId2);
                return compareByIntColSortAsc(listing1.bedrooms, listing2.bedrooms);
            }
    
            function compareByBathrooms(mlsId1, mlsId2) {
                var listing1 = listings.getItem(mlsId1);
                var listing2 = listings.getItem(mlsId2);
                return compareByIntColSortAsc(listing1.bathrooms, listing2.bathrooms);
            }
    
            function compareByPricePerSquareFeet(mlsId1, mlsId2) {
                var listing1 = listings.getItem(mlsId1);
                var listing2 = listings.getItem(mlsId2);
                if (listing1.squareFeet == null || listing1.squareFeet == 0) {
                        if (listing2.squareFeet == null || listing1.squareFeet == 0) {
                            return 0;
                        }
                        return -(listing2.price/listing2.squareFeet);
                } else if (listing2.squareFeet == null || listing2.squareFeet == 0) {
                    return (listing1.listingPrice/listing1.squareFeet);
                }
                return (listing2.listingPrice/listing2.squareFeet) - (listing1.listingPrice/listing1.squareFeet);
            }
    
            function compareByIntColSortAsc(col1val, col2val) {
                return col1val - col2val;
            }
    
            function compareByIntColSortDesc(col1val, col2val) {
                return col2val - col1val;
            }
            var comparator = this.compareByPrice;
    
            switch (this.sortBy) {
                case "price-per-sq-ft" :
                    comparator = compareByPricePerSquareFeet;
                    break;
                case "bedrooms" :
                    comparator = compareByBedrooms;
                    break;
                case "bathrooms" :
                    comparator = compareByBathrooms;
                    break;
            }
            this.sortedListings.sort(comparator);
        }

  3. #3
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwolfe View Post
    alright well i figured out how to do it, i just put the compare functions (as normal functions inside the sort function as follows
    You could also do something like the following.


    In the sortListings function

    window.comparatorContext = this;

    this.sortedListings.sort(comparator);

    In the comparator function

    window.comparatorContext.listings

    But if your way works then you might as well do it that way.

  4. #4
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, this implementation looks a bit too cumbersome to me. In javascript it's easy to program callbacks using closures and first-class functions.

    Assume we've got a Listing object, that has a set of compare_by methods, e.g. compare_by_price, compare_by_bedrooms etc. and let Listings be an array of Listing objects. Then you can sort Listings like this:

    Code:
    sort_by = function(what) {
    	return Listings.sort(function(a, b) {
    		return a["compare_by_" + what](b);
    	}
    }
    No switches, no intermediate functions, no clutter.

  5. #5
    SitePoint Enthusiast
    Join Date
    Feb 2008
    Posts
    62
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I started reading about the call and apply methods yesterday after seeing this thread. I couldn't figure out how to use either because what you need to apply the magic to is the callback. Isn't there a way to use apply or call in this situation. Not that it would be a better solution, I was just frustrated yesterday after not being able to figure out how to get it to work.

  6. #6
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually, apply would be indeed a better solution for the above. Instead of passing string name of the function we can pass the function itself to the sort_by method:
    Code:
    sort_by = function(compare_func) {
    	return Listings.sort(function(a, b) {
    		return compare_func.apply(a, b);
    	}
    }
    For example
    Code:
    Listings.sort_by(Listing.compare_by_price)


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •