qqruza
qqruza

Reputation: 1417

Search by multiple keys and values, Javascript

I'm trying to make a search function. The number of filters will change dynamically, a number of keys can be different, and the number of values, too.

My code looks like:

var data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Resla"}]
var keys = ["color", 'model'];
var values = ["Re"];

var result = data.filter(function(e) {
  return keys.every(function(a) {
    return values.includes(e[a])
  })
})
console.log(result);

Is it possible to search with - startsWith() and not includes()? I guess everything should be in toLowerCase() as well?

Also can I have two separate results as two arrays if results found in one key then it should individual array? So results will be like:

[{ colors: [{"id":"123","color":"Red","model":"Tesla"},{"id":"125","color":"Red","model":"Audi"}], models: [{"id":"126","color":"Blue","model":"Resla" }] }]

Thank you very much in advance.

Upvotes: 1

Views: 2225

Answers (2)

adiga
adiga

Reputation: 35222

  • You need to check keys.some and not keys.every. This will check if the value is part of at least one of the keys and not all of them.

  • For values, you could create a dynamic regex with alternation and test value against the regex. So, values = ["Re", "Ho"] will create /Re|Ho/

const data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Resla"}],
      keys = ["color", 'model'],
      values = ["Ho"],
      regex = new RegExp(values.join('|')),
      output =  data.filter(e =>  keys.some(k => regex.test(e[k])) )
      
console.log(output);
If you want to individual results for each key, you can loop through the keys and check for the regex individually.

const data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Resla"}],
      keys = ["color", 'model'],
      values = ["Ho", "Re"],
      regex = new RegExp(values.join('|')),
      group = {}
      
for (const o of data) {
  for (const k of keys) {
    if (regex.test(o[k])) {
      group[k] ||= []
      group[k].push(o)
    }
  }
}

console.log(group);

Upvotes: 2

Hassan Imam
Hassan Imam

Reputation: 22534

You can iterate through each key and value and look it up in object array using array#reduce

const data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Resla"}],
      keys = ["color", 'model'],
      values = ["Re"],
      initial = Object.assign(...keys.map(k => ({[`${k}s`]: [] }))),
      result = data.reduce((r, o) => {
       keys.forEach(k => {
        values.forEach(val => {
          if(o[k] && o[k].startsWith(val)) {
            r[`${k}s`].push(o);
          }
        });
       });
       return r;
      },initial);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Related Questions