Finding multiple filters in JSON using Javascript forEach and indexOf

I have data in JSON format in which I need to search. There are various tags, and when I click on them, it searches in JSON and returns the elements that have these tags. For this, I use the js function. It works correctly the first time, but when I click on the second filter in a function, it returns incorrect data.

Available Filters:

Snap

  • Soft cover
  • Binding
  • Audiobook
  • Boxed set

Category

  • Classic rock
  • Pop
  • Pop rock
  • Electro pop
  • Soft rock
  • Rock

Tongue

  • Deutsch
  • English
  • French

Author

  • the male
  • Female
  • male / female

Here is the JSON and the code I'm using:

var m = { "Books": [{ "title": "Book 1", "binding": "paperback", "category": "pop", "language": "english", "author": "male" }, { "title": "Book 2", "binding": "hardcover", "category": "pop rock,electro pop", "language": "french", "author": "female" }, { "title": "Book 3", "binding": "audiobook", "category": "soft rock", "language": "german", "author": "male,female" }, { "title": "Book 4", "binding": "boxed set", "category": "rock,classic rock", "language": "english", "author": "female,male" }, { "title": "Book 5", "binding": "paperback", "category": "electro pop,rock,classic rock", "language": "french", "author": "male/female" }, { "title": "Book 6", "binding": "paperback", "category": "rock", "language": "french", "author": "male" } ] } // a function which accepts key which is one of binding,category,language,author. // the array will be filtered on this key function getFilteredElement(key, value) { var bookFilter = []; m.Books.forEach(function(item){ var getFilterField = item[key]; // since the value is a string, so splitting it and creating an array var keyArray = item[key].split(','); // now checking if the passed value has a presence in the above array if (keyArray.indexOf(value) !== -1) { // if present pushed the book name bookFilter.push(item.title); } }); // returning the array of books return bookFilter; } console.log(getFilteredElement('category', 'rock')) 

For example,. When I press category = rock , it returns Book 4, Book 5 and Book 6 , but if I press category = rock and language = french , the returned result should only be Book 5 , but it will not return the correct results.

Can anyone help.

+5
source share
3 answers

You can use the object for filters and take the keys search key and value as the search value for the string.

Comma-separated properties are separated and checked.

 function getBooks(filters) { return array.Books.filter(function (o) { return Object.keys(filters).every(function (k) { return o[k].split(',').some(function (v) { return v === filters[k]; }); }); }); //.map(function (o) { // return o.title; //}); } var array = { Books: [{ title: "Book 1", binding: "paperback", category: "pop", language: "english", author: "male" }, { title: "Book 2", binding: "hardcover", category: "pop rock,electro pop", language: "french", author: "female" }, { title: "Book 3", binding: "audiobook", category: "soft rock", language: "german", author: "male,female" }, { title: "Book 4", binding: "boxed set", category: "rock,classic rock", language: "english", author: "female,male" }, { title: "Book 5", binding: "paperback", category: "electro pop,rock,classic rock", language: "french", author: "male/female" }, { title: "Book 6", binding: "paperback", category: "rock", language: "french", author: "male" }] }; console.log(getBooks({ category: 'rock' })); console.log(getBooks({ category: 'rock', language: 'french' })); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
+2
source

Usage can use Array.prototype.filter() , Array.prototype.reduce() and String.prototype.includes() to create a filtering system where an array of filters consisting of key value can be gradually added to clarify array of books .

See a practical example below.

 // Books. const books = [ { "title": "Book 1", "binding": "paperback", "category": "pop", "language": "english", "author": "male" }, { "title": "Book 2", "binding": "hardcover", "category": "pop rock,electro pop", "language": "french", "author": "female" }, { "title": "Book 3", "binding": "audiobook", "category": "soft rock", "language": "german", "author": "male,female" }, { "title": "Book 4", "binding": "boxed set", "category": "rock,classic rock", "language": "english", "author": "female,male" }, { "title": "Book 5", "binding": "paperback", "category": "electro pop,rock,classic rock", "language": "french", "author": "male/female" }, { "title": "Book 6", "binding": "paperback", "category": "rock", "language": "french", "author": "male" } ] // Query. const query = (books, filters) => { // filters = [{key: 'category', value: 'string'}..] return books.filter((book) => { // Found? return filters.reduce((found, filter) => { if (!(book[filter.key].includes(filter.value))) return false return found }, true) }) } // Log. console.log('Category = Rock', query(books, [{key: 'category', value: 'rock'}])) console.log('Category = Rock + Language = French', query(books, [{key: 'language', value: 'french'}])) console.log('Paperback', query(books, [{key: 'binding', value: 'paperback'}])) // Paperback. console.log('Paperback + Male', query(books, [{key: 'binding', value: 'paperback'}, {key: 'author', value: 'male'}])) // Paperback + Male. console.log('Paperback + Male + Pop', query(books, [{key: 'binding', value: 'paperback'}, {key: 'author', value: 'male'}, {key: 'category', value: 'pop'}])) // Paperback + Male + Pop. 
+1
source

This approach solves your problem:

 function applyFilters(books, filters) { for(let filter of filters) { var key = filter[0]; var value = filter[1]; books = getFilteredElement(books, key, value); } return books.map(book => book.title); } // a function which accepts key which is one of binding,category,language,author. // the array will be filtered on this key function getFilteredElement(books, key, value) { var bookFilter = []; books.forEach(function(item){ var getFilterField = item[key]; // since the value is a string, so splitting it and creating an array var keyArray = item[key].split(','); // now checking if the passed value has a presence in the above array if (keyArray.indexOf(value) !== -1) { // if present pushed the book name bookFilter.push(item); } }); // returning the array of books return bookFilter; } var filtersToApply = [["category", "rock"], ["language", "french"]]; var bookFilter = applyFilters(m.Books, filtersToApply); console.log(bookFilter); 
0
source

Source: https://habr.com/ru/post/1274030/


All Articles