【问题标题】:In JavaScript, how can I filter an array with dynamic conditions?在 JavaScript 中,如何过滤具有动态条件的数组?
【发布时间】:2020-04-24 03:02:13
【问题描述】:

这是我在网站上遇到的问题的简化示例。

我有一个包含这样一些项目的数组:

var testArr = ["Jeremy", "John", "Hank", "Hal"];

如果我知道过滤器是什么,我可以像这样过滤它:

var testArr2 = testArr.filter(function (item){
    return item.length < 5 &&
            item.startsWith("H");
});

在我的网站上,我有一个界面,用户可以在其中选择多个过滤器。在此示例中,用户将能够决定按长度或值的开头进行过滤。我需要能够动态地向return 添加条件或找到其他过滤方式。我在他的 SO 线程 javascript filter array multiple conditions 上尝试了一些答案,但我无法将其应用于我的示例。

提前致谢!

【问题讨论】:

  • 使用代码实现“我的过滤器为空或项目以我的过滤器开头。”
  • 只有你能想出这个代码,但听起来你需要一些 booleans
  • 感谢所有回答这个问题的人!我从提供的每个答案中都学到了一些东西。这就是为什么 SO 是一个很棒的资源。

标签: javascript arrays


【解决方案1】:

您可以将单个过滤器作为函数存储在数组中,并通过使用实际值检查每个过滤器函数来过滤。

var array = ["Jeremy", "John", "Hank", "Hal", "Hermine"],
    filters = {
        smallerThanFive: item => item.length < 5,
        startsWithH: item => item.startsWith('H')
    }
    selected = [filters.smallerThanFive, filters.startsWithH],
    result = array.filter(item => selected.every(f => f(item)));

console.log(result);

【讨论】:

  • 这个是为我做的!我可以通过将过滤器推入过滤器数组来动态添加过滤器。谢谢!
  • 这适用于我的数据源是平面的或只是对象中的对象但我们可以在上面的代码中修改什么来满足“const filters = { greaterThanPrice: item => item.rooms.rPrice > 200 }" 其中房间是一个对象数组,而 rPrice 是其中一个对象的价格 :-) 所以我的数据结构是 {property{ pId: 1, rooms: [ {rPrice:50}, {rPrice:100} ] }}, {property{ pId: 2, 房间: [ {rPrice:75}, {rPrice:125} ] }}
  • @ssedwards,这不仅仅是在评论部分提出另一个问题。请在尝试的同时提出一个新问题。
  • 好的,我想我是通过使用以下方法弄明白的:{greaterThanPrice: item => item.rooms.some(r => r.rPrice > 180)}
  • @NinaScholz 谢谢你回来找我 :-)
【解决方案2】:

你不能只问用户两个参数,长度和起始值,将它们存储在两个变量中,然后将它们用作 filter() 函数的值吗?
像这样的:

var maxLength = userLengthInput; //Get this value from the user.
var startValue = userStartValueInput; //Get this value from the user.

var testArr2 = testArr.filter(function (item){
    return item.length < maxLength && item.startsWith(startValue);
});

【讨论】:

  • OP 希望让用户决定其中一个或两个
【解决方案3】:

您可以隔离案例并单独返回 true 或 false,或者您可以将所有条件组合成一个大布尔表达式。

例如:

var testArr2 = testArr.filter(function (item){
    if (checkBoxCheckedForRejectStringWithJustOneCharacter() &&
        item.length === 1) return false;
    if (checkBoxCheckedForAcceptingAllStringsBeginningWithZ() &&
        item[0].toLowerCase() === "z") return true;
    return item.length < 5 &&
            item.startsWith("H");
});

这仅取决于您的 UI,您可以自定义代码中的条件。

【讨论】:

    【解决方案4】:

    问吧。

    const testArr = ["Jeremy", "John", "Hank", "Hal"];
    
    const filterIt = (arr,len,sw) => {
      return arr.filter(item => {
        let okLength = len === null || (len && len > 0 && item.length<len);
        let okSw = !sw  || (sw && item.startsWith(sw));
        return okLength && okSw;
      })
    }
    
    console.log(filterIt(testArr,null,"H"))
    console.log(filterIt(testArr,5))
    console.log(filterIt(testArr,4,"H"))

    【讨论】:

      【解决方案5】:

      为了简单的使用,最好有一个包含所有过滤逻辑的类Filter。然后用我们想要的过滤器实例化它,并将它们应用到我们已有的输入。

      看看下面的代码。它更具可读性。

      为了可扩展性,您还可以将所有过滤逻辑放入单独的类中,并在您的主 Filter 类中使用这些类。

      var testArr = ["Jeremy", "John", "Hank", "Hal"];
      
      function Filter(filters) {
        this.filters = filters;
      }
      
      Filter.prototype.filterByLength = function(items, value) {
        return items.filter(function(item) {
          return item.length < value
        })
      };
      
      Filter.prototype.filterByValue = function(items, value) {
        return items.filter(function(item) {
          return item.startsWith(value);
        })
      };
      
      Filter.prototype.filter = function(items) {
        return Object.entries(this.filters)
          .reduce(function (final, [key, value]) {
          return final && this[key](items, value)
        }.bind(this), true)
      };
      
      var instance = new Filter({
        filterByLength: 5,
        filterByValue: 'H'
      })
      
      var result = instance.filter(testArr)
      console.log(result)

      【讨论】:

      • 如果 filterBy 是成员而不是原型分配,会不会更具可读性?
      • @mplungjan 是的,如果您只有这两个过滤器。由于动态性,我将它们分成原型,以便以后用作单独的类。感谢您的评论。
      【解决方案6】:

      这里是 HTML/CSS/JS 的示例:

      https://codepen.io/Karkael/pen/zYxpWqR

      function showFilteredList() {
        var filterLength = formFilter["string-length"].value;
        var filterStarts = formFilter["string-starts"].value;
        showList(testArr.filter(function (item) {
          if (filterLength.length && item.length >= parseInt(filterLength)) return false;
          if (filterStarts.length && !item.startsWith(filterStarts)) return false;
          return true;
        }));
      }
      

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2019-03-02
        • 2021-11-20
        • 1970-01-01
        • 2023-03-21
        • 2022-01-24
        • 2020-01-22
        • 2022-01-03
        • 2021-07-02
        • 1970-01-01
        相关资源
        最近更新 更多