views:

224

answers:

3

I have the following JavaScript JSON array of real estate home objects:

var json = { 'homes' : 
[
    {
        "home_id":"1",
        "price":"925",
        "sqft":"1100",
        "num_of_beds":"2",
        "num_of_baths":"2.0",
    },
    {
        "home_id":"2",
        "price":"1425",
        "sqft":"1900",
        "num_of_beds":"4",
        "num_of_baths":"2.5",
    },
    // ... (more homes) ...     
]}
var xmlhttp = eval('(' + json + ')');
homes = xmlhttp.homes;

What I would like to do is be able to perform a filter on the object to return a subset of "home" objects.

For example, I want to be able to filter based on: price, sqft, num_of_beds, and num_of_baths.

Question: How can I perform something in javascript like the pseudo-code below:

var newArray = homes.filter(
price <= 1000 & 
sqft >= 500 & 
num_of_beds >=2 & 
num_of_baths >= 2.5);

Note, the syntax does not have to be exactly like above. This is just an example.

A: 

You could do this pretty easily - there are probably many implementations you can choose from, but this is my basic idea (and there is probably some format where you can iterate over an object with jQuery, I just cant think of it right now):

function filter(collection, predicate)
{
    var result = new Array();
    int length = collection.length;

    for(var j = 0; j < length; j++)
    {
        if(predicate(collection[j]) == true)
        {
             result.push(collection[j]);
        }
    }

    return result;
}

And then you could invoke this function like so:

filter(json, function(element)
{
    if(element.price <= 1000 && element.sqft >= 500 && element.num_of_beds > 2 && element.num_of_baths > 2.5)
        return true;

    return false;
});

This way, you can invoke the filter based on whatever predicate you define, or even filter multiple times using smaller filters.

Tejs
+5  A: 

You can use the Array.prototype.filter method:

homes.filter(function (el) {
  return el.price <= 1000 &&
         el.sqft >= 500 &&
         el.num_of_beds >=2 &&
         el.num_of_baths >= 2.5;
});

This method is part of the new ECMAScript 5th Edition standard, and can be found on almost all modern browsers.

For IE, you can include the following method for compatibility:

if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun /*, thisp*/) {
    var len = this.length >>> 0;
    if (typeof fun != "function")
    throw new TypeError();

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
      if (i in this) {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
        res.push(val);
      }
    }
    return res;
  };
}
CMS
what is /*, thisp*/ ?
JGreig
@JGreig: Is just a comment to indicate that an optional argument may be passed, the argument is not specified directly because the ECMA standard precisely says that this method should expect only one argument (`Array.prototype.filter.length == 1;`). When you use the second argument, it will be used as the `this` value inside the callback function.
CMS
@CMS, Are you sure this code works? This is returning an empty array, even when I set the price to be really high and the sqft/beds/baths to be really low. Are you sure this code works?
JGreig
@JGreig: Yes, it works, you should check your criteria, maybe you could post a more complete example of your JSON in http://pastie.org or http://jsbin.com and the criteria you are using to filter, so I can help you better.
CMS
@CMS, I've updated my original post with the live web site. It would be great if you could look at the code. I really, really appreciate it. Thanks in advance
JGreig
@CMS, any luck to see what's wrong with my code?
JGreig
@CMS, you're crazy awesome. thanks so much for the help. all working
JGreig
@JGreig, you're welcome!, don't forget to include the compatibility method for IE...
CMS
A: 

You can try using framework like jLinq - following is a code sample of using jLinq

var results = jLinq.from(data.users)
.startsWith("first", "a")
.orEndsWith("y")
.orderBy("admin", "age")
.select();

For more information you can follow the link http://www.hugoware.net/projects/jlinq

Rutesh Makhijani