简体   繁体   中英

Trying to filter a JSON based on several fields in JS

First of all, my apologies if my question is too obvious but I my knowledge is limited and I don't get how to achieve what I am trying. I have a JSON file as source of the data (songs) and I am trying to filter that data based on several fields (level, name, artist, etc.).

Example of some data from the JSON:

[
  {"artist": "Black",
    "categories": "Arreglos",
    "date": 1639127185000,
    "level": "Fácil",
    "musicStyle": "Pop/Rock",
    "name": "Wonderful Life",
    "practice": "n/a",
    "preloadID": "Wonderful_Life",
    "subtitle": "Fácil",
  },
{"artist": "",
    "categories": "Arreglos",
    "date": 1587948049309,
    "image": "./images/arreglos/a_million_dreams.jpeg",
    "level": "Fácil",
    "musicStyle": "Film/TV",
    "name": "A million dreams",
    "preloadID": "AMillionDreams_Facil",
    "subtitle": "Fácil",
  },
{"artist": "",
    "categories": "Arreglos",
    "date": 1587948046688,
    "image": "./images/arreglos/a_million_dreams.jpeg",
    "level": "Principiante",
    "musicStyle": "Film/TV",
    "name": "A million dreams",
    "preloadID": "AMillionDreams_Principiante",
    "subtitle": "Principiante",
  },
{"artist": "Vanessa Carlton",
    "categories": "Arreglos",
    "date": 1602939064030,
    "level": "Fácil",
    "musicStyle": "Pop/Rock",
    "name": "A thousand miles",
    "preloadID": "AThousandMiles_Facil",
    "subtitle": "Fácil",
  },
{"artist": "Vanessa Carlton",
    "categories": "Arreglos",
    "date": 1602939064033,
    "level": "Muy fácil",
    "musicStyle": "Pop/Rock",
    "name": "A thousand miles",
    "preloadID": "AThousandMiles_MuyFacil",
    "subtitle": "Muy fácil",
    "tonality": ""
  },
]

And this is the script I have to try to filter the data.

let filteredItems = [];
let filterLevel=this.context.appActions.dataSlots['ds_LevelFilter'];
let filterStr=this.context.appActions.dataSlots['ds_SearchFilter'];
filterStr=filterStr.toLowerCase();
      
      items.forEach(item => {
        if (item["artist"].toLowerCase().includes(filterStr) || item["name"].toLowerCase().includes(filterStr) ) {
          filteredItems.push(item);
          }
      });
      
      items.forEach(item => {
        if (item["level"] == filterLevel) {
          filteredItems.push(item);
        }
      });
      
      items = filteredItems.sort((a, b) => {
              return new Date(b.date) - new Date(a.date);
            }).slice(0,this.context.appActions.dataSlots['ds_limitQuery']);

return items;

For filterStr, I have a text field where the user would write a search and if that is included in name or artist, it should return the resulted documents.

In filterLevel I have a picker with several values (Easy, Medium, etc. in Spanish) and it should be equal to the field "level" from the data.

I am not sure if the code shows what I am trying but if I use just the first if block (name and artist) it works perfectly. But if I add the second, it gives me an error of duplicated keys (it is a React project). I am guessing the script is not correct.

I would really appreciate some guidance. Thanks!

Use an Object filter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

 const songs = [ { id: 1, name: 'Golden Hour', artist: 'Kacey Musgraves', level: 100 }, { id: 2, name: 'King Size Manger', artist: 'Josh Turner', level: 122 }, { id: 3, name: 'Legend', artist: 'Bob Marley', level: 100 }, { id: 4, name: 'Catch A Fire', artist: 'Bob Marley', level: 100 }, { id: 5, name: 'Fine Line', artist: 'Harry Styles', level: 68 }, ] function filterSongs(filterStr = '', filterLevel = null) { return songs.filter(item => { const context = filterStr.toLowerCase() // Filter on level else ignore by always returning true. let result = filterLevel == null? true: (item.level === filterLevel) // If result is false because level was set and did not match then skip filterStr check. // If result is true because level was ignored or matched then search if filterStr has value. if(result && filterStr.length) { result = item.artist.toLowerCase().includes(context) || item.name.toLowerCase().includes(context) } return result }) } console.log('Search for Harry', filterSongs('Harry')) console.log('Search for level 100', filterSongs('', 100)) console.log('Search for Golden with level 100', filterSongs('Golden', 100)) console.log('Search for Bob', filterSongs('Bob'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM