How to filter a list using an array of keywords?

Viewed 78

Basically, I want to filter a list so it only shows items containing BOTH keywords inside the array. Ex.:

searchArray = ['sys', 'config']

If the user type 'sys config', should only show "System configuration" and hide other items.

So far I came up with this, but it's not working properly, cause it shows items that contains one of the words and not both.

var searchArray = search.split(" ");

for(x in searchArray){
    filteredMenu = $('.texto:contains(\'' + searchArray[x] + '\')')
}
3 Answers

Check that .every one of the keywords is included:

const texts = [...$('.texto')]
  .filter(element => searchArray.every(
    substr => element.textContent.includes(substr)
  ));

Demo:

searchArray = ['sys', 'config']

const texts = [...$('.texto')]
  .filter(element => searchArray.every(
    substr => element.textContent.includes(substr)
  ));
for (const text of texts) {
  console.log(text);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="texto">
foo
</div>
<div class="texto">
config
</div>
<div class="texto">
sys config
</div>
<div class="texto">
system configuration
</div>
<div class="texto">
sys
</div>
<div class="texto">
bar
</div>

Also, in some cases it is useful to construct a regular expression ("regex") string, and to use this to perform the search.

I used the solution posted by a guy in Brazillian SO. Adding multiple :contains seems to work perfectly. Also, the answer from CertainPerformance works great!

var arrayBusca = ["config", "empresa"];
var stringBusca = '';

arrayBusca.forEach((item) => stringBusca = stringBusca.concat(`:contains("${item}")`));

console.log(stringBusca); // output: :contains("config"):contains("empresa")
Related