Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array filtering with multiple conditions javascript

Tags:

javascript

I can't figure out how to filter an array with multiple conditions. I have a search filter form with 2 select, 1 checkboxes fieldset and 1 radio button fieldset. I have functions that return items that match chosen conditions. They work only separately. What is the best approach to find objects that match all conditions?

I tried to make if statements for all possible options, but code doesn't work correctly and it looks like there should be some better options to do so.

Here is function examples:

    function chooseRating(hotel) {
      return hotel.rating == e.target.value;
    }

    function chooseMeal(hotel) {
      return hotel.mealType == e.target.value;
    }


    function choosePlace(hotel)  {
      for (let l = 0; l < chosenPlace.length; l++) {
      if(chosenPlace[l].checked) {
        return hotel.region == e.target.value;
      }
              }
    }

How should I filter the array with that?

  let filteredCards = hotels.filter(function(hotel, index, hotels) {
    // ??
  });

Screenshot

User chooses his requirements for hotel and he should get hotels, that match all requirements. And if some of them not chosen, then they are don't count by default.

like image 429
Tonya Avatar asked Sep 26 '18 14:09

Tonya


People also ask

How do you add multiple conditions to a filter?

If you want to put multiple conditions in filter , you can use && and || operator.

Can you use filter on an array of objects JavaScript?

One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.


2 Answers

You can chain your filter() calls, like this:

// first filter
function filterRating(hotel) {
  return hotel.rating >= filters.rating;
}

// second filter
function filterMeal(hotel) {
  return !filters.mealType.length || hotel.mealType == filters.mealType;
}

// apply both filters to initial array
function update() {
  let filteredCards = hotels.filter(filterRating).filter(filterMeal);
};

Full example:

var filters = {
  rating: 4,
  mealType: ""
};

rating.value = filters.rating;
mealtype.value = filters.mealType;

rating.addEventListener("input", function() {
  filters.rating = rating.value;
  update();
});
mealtype.addEventListener("input", function() {
  filters.mealType = mealtype.value;
  update();
});

function filterRating(hotel) {
  return hotel.rating >= filters.rating;
}

function filterMeal(hotel) {
  return !filters.mealType.length || hotel.mealType == filters.mealType;
}

function update() {
  let filteredCards = getHotels().filter(filterRating).filter(filterMeal);
  console.log(filters);
  output.innerHTML = filteredCards.map(hotel => `<span>${hotel.name}</span>`).join("");
};
update();

function getHotels() {
  return [{
      name: "A",
      rating: 5,
      mealType: "full"
    },
    {
      name: "B",
      rating: 4,
      mealType: "full"
    },
    {
      name: "C",
      rating: 4,
      mealType: "breakfast"
    },
    {
      name: "D",
      rating: 5,
      mealType: "breakfast"
    }
  ];
}
input,
select {
  margin: 1em 0
}

#rating {
  width: 3em
}

#output span {
  display: inline-block;
  border: 1px solid black;
  padding: 0.5em;
  margin: 0.5em;
}
Rating &gt;= <input id="rating" value="5" type="number"><br> Meal:
<select id="mealtype">
  <option value="">any</option>
  <option>breakfast</option>
  <option>full</option>
</select><br>
<p id="output"></p>
like image 150
Chris G Avatar answered Nov 05 '22 23:11

Chris G


If I've understood the problem correctly, you can just pass all your matching functions to the filter() test function and require them all to be truthy using AND operators:

let filteredCards = hotels.filter(hotel => chooseRating(hotel) && chooseMeal(hotel) && choosePlace(hotel))

This is the same as:

let filteredCards = hotels.filter(hotel => {
  return chooseRating(hotel) && chooseMeal(hotel) && choosePlace(hotel)
})

This is also the same:

let filteredCards = hotels.filter(function(hotel) {
  return chooseRating(hotel) && chooseMeal(hotel) && choosePlace(hotel)
})
like image 32
camslice Avatar answered Nov 05 '22 23:11

camslice