2
votes

Tableau de filtres basé sur un tableau de filtres en Javascript

J'ai un tableau d'utilisateurs et aussi un tableau de filtres.

J'ai besoin de filtrer les utilisateurs en fonction du tableau de filtres mais quand je le ferai, il filtrera sur un tableau mais pas sur les autres

Mon objet filtres ressemble à ceci:

applyFilter = (visable) => {
    let { filters, users } = this.state;
    const { subjects, locations, levels } = filters;


    let filteredUsers = [];
    const filteredData = users.filter((user) =>
      user.subjects.some(subject => subjects.includes(subject)) ||
      locations.some(location => location === user.location) ||
      user.levels.some(level => levels.includes(level))
    );

    console.log(filteredData)


    if (!subjects.length && !locations.length && !levels.length) {
      filteredUsers = users;
    } else {
      filteredUsers = filteredData;
    }

    this.setState({
      filterModalVisible: visable,
      filteredResults: filteredUsers.length >= 0 ? filteredUsers : [],
    });
  }

Mes utilisateurs ressemblent à ceci:

[{
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
]

D'après le filtre ci-dessus, une fois filtré, les utilisateurs ne doivent en être qu'un car il contient "Art" et "Laois":

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]

Mais j'obtiens toujours les deux utilisateurs:

MODIFIER Mon code:

filters: {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}


1 commentaires

veuillez ajouter votre code.


5 Réponses :


1
votes

Vous pouvez le faire en utilisant les méthodes filter et every en vérifiant si chaque élément de la valeur des filtres existe dans la valeur utilisateur avec la même clé.

p>

const filters = {"levels":[],"locations":["Laois"],"subjects":["Art"]}
const users = [{"email":"example1@gmail.com","levels":["Ordinary"],"locations":"Laois","subjects":["Art","German"]},{"email":"example2@gmail.com","levels":["Higher","Ordinary"],"locations":"Laois","subjects":["English","German"]}]

const res = users.filter(user => {
  return Object.entries(filters)
    .every(([key, value]) => {
      if (Array.isArray(value)) {
        return value.every(filter => {
          return user[key] && user[key].includes(filter)
        })
      } else {
        return user[key] == value
      }
    })
})

console.log(res)


0 commentaires

0
votes

Utilisation du filtre à l'intérieur du filtre

const filters = {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]
console.log(users.filter((e) => {
  var arr = e.subjects.filter((x) => filters.subjects.includes(x))
  if (arr.length > 0 && filters.locations.includes(e.location))
    return e
}))


0 commentaires

1
votes

Vous pouvez essayer avec filter()

const filters = {
  levels: [],
  locations: ['Laois'],
  subjects: ['Art']
}

const users = [
  {
    email: 'example1@gmail.com',
    levels: ['Ordinary'],
    location: 'Laois',
    subjects: ['Art', 'German']
  },
  {
    email: 'example2@gmail.com',
    levels: ['Higher', 'Ordinary'],
    location: 'Laois',
    subjects: ['English', 'German']
  }
]

var res = users.filter(info => info.location==filters.locations[0] && info.subjects.includes(filters.subjects[0]));

console.log(res);


0 commentaires

1
votes

Vous pouvez avoir une solution générique pour n'importe quelle clé de filtre en utilisant Array.filter , Array.some et Array.includes

  • Utilisez filter pour valider chaque entrée par rapport à toutes les conditions de filtre
  • Si une condition de filtre a une liste vide, continuez à vérifier la condition suivante
  • Pour les emplacements , comme la clé de filtre est différente de la clé dans l'objet , ajoutez une vérification spécifique pour celui où nous vérifions l'emplacement à inclure dans le tableau des emplacements
  • Pour les autres champs, vérifiez l'existence d'au moins 1 entrée dans le tableau qui existe dans la valeur du filtre. S'il existe une valeur, continuez à vérifier la condition suivante.
  • Après vérification de la condition, confirmez si l'entrée est valide, sinon rompez la boucle et renvoyez false

let filters = {levels: [],locations: ['Laois'],subjects: ['Art']};
let users = [{email: 'example1@gmail.com',levels: ['Ordinary'],location: 'Laois',subjects: ['Art', 'German']},{email: 'example2@gmail.com',levels: ['Higher', 'Ordinary'],location: 'Laois',subjects: ['English', 'German']}];

users = users.filter(v => {
  let response = true;
  for (let filter in filters) {
    if(!filters[filter].length) continue;
    if(filter === "locations") {
      response = response && filters.locations.includes(v.location)
    } else response = response && v[filter].some(f => filters[filter].includes(f));
    if(!response) break;
  }
  return response;
});
console.log(users);


0 commentaires

0
votes
  1. Vous devez utiliser && au lieu de || si vous souhaitez remplir toutes les conditions
  2. Selon vos besoins, vous devez tous les correspondre si le tableau de filtres est vide, vous pouvez donc simplement contourner la vérification pour ce cas
  3. applyFilter = (visable) => {
        let { filters, users } = this.state;
        const { subjects, locations, levels } = filters;
    
        const filteredResults = users.filter((user) =>
            (!subjects.length || user.subjects.some(subject => subjects.includes(subject))) &&
            (!locations.length || locations.some(location => location === user.location)) &&
            (!levels.length || user.levels.some(level => levels.includes(level)))
        );
    
        this.setState({
            filterModalVisible: visable,
            filteredResults
        });
    }

0 commentaires