【问题标题】:Array filtering with multiple conditions javascript具有多个条件javascript的数组过滤
【发布时间】:2019-03-02 08:50:53
【问题描述】:

我不知道如何过滤具有多个条件的数组。我有一个带有 2 个选择、1 个复选框字段集和 1 个单选按钮字段集的搜索过滤器表单。我有返回符合所选条件的项目的函数。他们只能单独工作。找到符合所有条件的对象的最佳方法是什么?

我尝试为所有可能的选项创建 if 语句,但代码无法正常工作,看起来应该有一些更好的选项可以这样做。

这里是函数示例:

    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;
      }
              }
    }

我应该如何过滤数组?

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

用户选择他对酒店的要求,他应该得到符合所有要求的酒店。如果其中一些未选择,则默认情况下不计入。

【问题讨论】:

  • 请添加您期望的输入和输出。
  • 如果没有e,这些功能将无法工作,但该事件是一次性的,您需要&lt;input&gt;value
  • @shubham-gupta 我提供了一些额外的信息。这是你要求的吗?
  • @chris-g 一开始我使用的是值,但它也不能正常工作

标签: javascript


【解决方案1】:

您可以像这样链接您的 filter() 调用:

// 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);
};

完整示例:

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>

【讨论】:

【解决方案2】:

假设你有这样的东西:

<select id="rating">Rating options here ...</select>
<select id="meals">Meals options here ...</select>

<fieldset id="places">
<input type="checkbox" value="one">place one</input>
<input type="checkbox" value="two">place two</input>
</fieldset>

<input type="radio" name="rad" value="rad_one">radio one</input>
<input type="radio" name="rad" value="rad_two">radio two</input>

您可以使用以下内容过滤酒店数组:

let selected_rating = document.querySelector('#rating').value;
let selected_meal = document.querySelector('#meals').value;
let selected_places = [].map.call(document.querySelectorAll('#places input[type="checkbox"]:checked'),function(elem){ return elem.value});
let selected_radio = document.querySelector('[name="rad"]:checked').value;

let filteredCards = hotels.filter(function(hotel){
    return hotel.rating == selected_rating
        && hotel.mealType == selected_meal
        && selected_places.indexOf(hotel.place) != -1
        && hotel.region == selected_radio;
});

【讨论】:

    【解决方案3】:

    如果我正确理解了问题,您可以将所有匹配函数传递给 filter() 测试函数,并使用 AND 运算符要求它们全部为真:

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

    这与:

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

    这也是一样的:

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

    【讨论】:

      【解决方案4】:

      简洁实用的解决方案

      const combineFilters = (...filters) => (item) => {
          return filters.map((filter) => filter(item)).every((x) => x === true);
      };
      

      然后你像这样使用它:

      const filteredArray = arr.filter(combineFilters(filterFunc1, filterFunc2));
      

      例如 filterFunc1 可能如下所示:

      const filterFunc1 = (item) => {
        return item === 1 ? true : false;
      };
      

      【讨论】:

        【解决方案5】:

        我必须使用 2 个输入对代码挑战进行过滤。

        如你所说,我的第一种方法是在一个过滤器中编写 if 条件,但没有用。

        我所做的是根据第一个条件创建一个新的数组过滤,然后使用第二个条件过滤返回的数组并且有效。

        希望这能解决您的问题:D

        【讨论】:

        • 我认为只有特定的过滤器顺序才有可能,这是无法更改的。例如,在这里,用户可以先选择地区,然后再选择餐食类型,反之亦然:)
        • 顺序无所谓。
        • 正如 Chris 所说,顺序无关紧要,如果您首先按第一个输入进行过滤并且用户没有更改任何内容,您将获得相同的数组,然后使用第二个输入进行过滤。
        猜你喜欢
        • 1970-01-01
        • 2021-07-05
        • 2015-10-28
        • 2019-11-20
        • 1970-01-01
        • 2019-12-29
        • 2021-01-26
        相关资源
        最近更新 更多