Categories
javascript

How to filter object array based on attributes?

643

I have the following JavaScript 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.

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.

4

  • 7

    This seems almost identical to stackoverflow.com/questions/1694717/…

    Apr 27, 2010 at 14:49


  • 3

    var json = { ... } JSON is a textual notation for data exchange. (More here.) If you’re dealing with JavaScript source code, and not dealing with a string, you’re not dealing with JSON.

    Nov 14, 2017 at 7:17

  • 1

    Don’t use eval. It’s generally bad practice and can cause performance issues. We just had to get rid of a bunch of those on a project because the processor was locking up.

    – SDH

    Jul 19, 2018 at 16:16


  • 2022- Just observed that ‘return’ is needed inside the filter function like in @Christian.C.Salvado’s answer

    Feb 9 at 11:14

926

You can use the Array.prototype.filter method:

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

Live Example:

var obj = {
    '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) ...     
    ]
};
// (Note that because `price` and such are given as strings in your object,
// the below relies on the fact that <= and >= with a string and number
// will coerce the string to a number before comparing.)
var newArray = obj.homes.filter(function (el) {
  return el.price <= 1000 &&
         el.sqft >= 500 &&
         el.num_of_beds >= 2 &&
         el.num_of_baths >= 1.5; // Changed this so a home would match
});
console.log(newArray);

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];
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }
    return res;
  };
}

9

  • 2

    @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.

    Apr 27, 2010 at 16:29


  • 1

    @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

    Apr 27, 2010 at 17:13

  • 2

    @JGreig: Yes, it works, you should check your criteria, maybe you could post a more complete example of your JSON in pastie.org or jsbin.com and the criteria you are using to filter, so I can help you better.

    Apr 27, 2010 at 17:24


  • @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

    Apr 27, 2010 at 17:32

  • 2

    @CMS It would be good if the answer includes the fact that a new array is returned, the original array is not modified. Even though this is said in the link provided, I find the answer without this is incomplete or inaccurate

    – GWorking

    Aug 27, 2016 at 10:48

48

I’m surprised no one has posted the one-line response:

const filteredHomes = json.homes.filter(x => x.price <= 1000 && x.sqft >= 500 && x.num_of_beds >=2 && x.num_of_baths >= 2.5);

…and just so you can read it easier:

const filteredHomes = json.homes.filter( x => 
  x.price <= 1000 && 
  x.sqft >= 500 && 
  x.num_of_beds >=2 && 
  x.num_of_baths >= 2.5
);

3

  • 18

    probably because it’s the same as CMS’s answer just with arrow functions

    – Erich

    Mar 15, 2020 at 18:35

  • It becomes a better answer with the newer versions of javascript for sure. var should be replaced with const, from my understanding.

    Jan 25 at 17:51

  • @Erich you have no idea how many people blindly copy and paste from SO. Rn I’m working on a project born in 2021, transpiled, and it’s full of var _self = this

    May 31 at 9:32

31

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

0