Krešimir Čoko
Krešimir Čoko

Reputation: 115

Filtering logic too strict

I'm trying to filter JSON data using the input[type="range"] element. I've reached a point where the filter works but it doesn't work perfectly.

Assume the default filters object looks like this:

filters = {
  price: 100,
  rating: 3,
  beds: 1,
  people: 1
}

Using this concept, and changing the values of the filters on input event the apartments get filtered very strictly, taking into consideration default values and the values the user actually wanted to filter by.

apartments = apartments.filter(apartment => {
    if (typeof apartment.price == 'string') {
        apartment.price = apartment.price.replace( /^\D+/g, '');
    }
    if (apartment.price <= (filters.price - 100) ||
        apartment.price >= filters.price) {
            return false;
    }
    if (apartment.rating != filters.rating)
        return false;
    if (apartment.beds != filters.beds)
        return false;
    if (apartment.people != filters.people)
        return false;
    else
        return true;
});

The question here is:

How can I make the filter better by only taking into account the value of the filter that the user changed?

I tried simply removing the default values but in that case there can never be a match for the filter because a value doesnt exist, and by putting a default value the apartments are strictly filtered with all 4 values even if the user only changed one of them.

Here is how the filters look on my app: http://prntscr.com/e6h3oq

This is one apartment represented in JSON:

{
    "id":1,
    "title":"ultrices posuere cubilia curae",
    "description":"Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.\n\nMaecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.",
    "date":"3/9/2016",
    "price":"£200.32",
    "rating":2,
    "address":"7 Harbort Drive",
    "beds":2,
    "people":2,
    "user":{
        "first_name":"Douglas",
        "last_name":"Hansen",
        "email":"[email protected]",
        "phone":"66-(363)851-6428"
    }
}

Upvotes: 1

Views: 61

Answers (1)

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22595

You just have to check if property is set in filter object. If it is undefined then return true from filter.

I would refactor your code a little bit:

Your check for beds, people and rating is very similar, so I would move it to curried function like this:

const propertyFilter = (propertyName) => {
       return (appartment) => {
           if(filters[propertyName] != undefined) {
               return  filters[propertyName]== apartment[propertyName]);
           }
           return true;
       }
}

You could also introduce function to handle parse logic of price and avoid mixing it with filtering code.

const parsePrice = (price) => {
    if (typeof price == 'string') {
            price = price.replace( /^\D+/g, '');
    }
    return price;
}

Then you could use it like this:

apartments
.filter(propertyFilter("people"))
.filter(propertyFilter("beds"))
.filter(propertyFilter("rating"))
.filter(apartment => {
    if(apartment.price != undefined) {
        const price = parsePrice(apartment.price);
        if (price <= (filters.price - 100) || price >= filters.price) {
            return false;
        }
    }
    return true;
})

Upvotes: 1

Related Questions