在JavaScript中,我如何使用动态条件过滤数组?

huangapple go评论65阅读模式
英文:

In JavaScript, how can I filter an array with dynamic conditions?

问题

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

我有一个包含如下内容的数组:

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

如果我知道要应用的过滤条件,我可以像这样对它进行过滤:

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

在我的网站上,我有一个用户可以选择多个过滤条件的界面。在这个示例中,用户可以选择按长度或以什么值开头来进行过滤。我需要能够动态添加条件到这个 return 语句中,或者找到其他过滤的方式。我尝试过一些在这个 Stack Overflow 帖子中的答案 https://stackoverflow.com/questions/31831651/javascript-filter-array-multiple-conditions,但在我的示例中应用起来有些困难。

提前感谢您的帮助!

英文:

This is a simplified example of a problem I have on a website.

I have an array with some items like this:

var testArr = [&quot;Jeremy&quot;, &quot;John&quot;, &quot;Hank&quot;, &quot;Hal&quot;];

If I know what the filters are, I can filter it like this:

var testArr2 = testArr.filter(function (item){
    return item.length &lt; 5 &amp;&amp;
			item.startsWith(&quot;H&quot;);
});

On my website, I have an interface where the user can select several filters. In this example, the user would be able to decide to filter by either length or what the value starts with. I need to be able to add conditions to that return dynamically or find some other way to filter. I tried some of the answers at he SO thread https://stackoverflow.com/questions/31831651/javascript-filter-array-multiple-conditions, but I am having trouble applying that to my example.

Thanks in advance!

答案1

得分: 19

You could store the single filters in an array as function and filter by checking each filter function with the actual value.

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);
英文:

You could store the single filters in an array as function and filter by checking each filter function with the actual value.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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);

<!-- end snippet -->

答案2

得分: 1

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

var maxLength = userLengthInput; // 从用户获取这个值。
var startValue = userStartValueInput; // 从用户获取这个值。

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

这段代码将根据用户提供的参数,过滤了testArr数组中的元素。

英文:

Can't you just ask the user the two parameters, the length and the starting value, storing them in two variables and then using them as the values for the filter() function?<br>
Something like this:

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 &lt; maxLength &amp;&amp; item.startsWith(startValue);
});

答案3

得分: 1

你可以将这些情况隔离开并分别返回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");
});

这取决于你的用户界面,你可以在你的代码中自定义这些条件。

英文:

You could isolate the cases and return true or false individually, or you can combine all conditions into one big boolean expression.

For example:

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

It just depends on your UI and you can customize the conditions in your code.

答案4

得分: 1

以下是您要翻译的内容:

"Just ask."

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"))
英文:

Just ask.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const testArr = [&quot;Jeremy&quot;, &quot;John&quot;, &quot;Hank&quot;, &quot;Hal&quot;];

const filterIt = (arr,len,sw) =&gt; {
  return arr.filter(item =&gt; {
    let okLength = len === null || (len &amp;&amp; len &gt; 0 &amp;&amp; item.length&lt;len);
    let okSw = !sw  || (sw &amp;&amp; item.startsWith(sw));
    return okLength &amp;&amp; okSw;
  })
}

console.log(filterIt(testArr,null,&quot;H&quot;))
console.log(filterIt(testArr,5))
console.log(filterIt(testArr,4,&quot;H&quot;))

<!-- end snippet -->

答案5

得分: 1

对于简单的用法,最好创建一个包含所有过滤逻辑的类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);

注意:这是代码的翻译版本,仅包含代码部分,不包括其他内容。

英文:

For simple usage it's better to have a class Filter containing all filtering logic. Then instantiate it with filters we want and apply them to the input we already have.

Take a look at the code below. It's more readable.

For the sake of extendability, you can also put all filtering logics into individual class and just use those classes in your main Filter class.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var testArr = [&quot;Jeremy&quot;, &quot;John&quot;, &quot;Hank&quot;, &quot;Hal&quot;];

function Filter(filters) {
  this.filters = filters;
}

Filter.prototype.filterByLength = function(items, value) {
  return items.filter(function(item) {
    return item.length &lt; 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 &amp;&amp; this[key](items, value)
  }.bind(this), true)
};

var instance = new Filter({
  filterByLength: 5,
  filterByValue: &#39;H&#39;
})

var result = instance.filter(testArr)
console.log(result)

<!-- end snippet -->

答案6

得分: 1

这是一个包含HTML/CSS/JS的示例:

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

希望对你有帮助!

英文:

Here an example with HTML/CSS/JS:

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

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

Hope it helps you!

huangapple
  • 本文由 发表于 2020年1月6日 22:58:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/59614299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定