JavaScript filtre tableau plusieurs conditions

Je veux simplifier un tableau d'objets. Supposons que j'ai le tableau suivant:

var users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
    },
    {
        name: 'Tom',
        email: 'tom@mail.com',
        age: 35,
        address: 'England'
    },
    {
        name: 'Mark',
        email: 'mark@mail.com',
        age: 28,
        address: 'England'
}];

Et filtre objet:

var filter = {address: 'England', name: 'Mark'};

Par exemple, j'ai besoin de filtrer tous les utilisateurs par adresse et nom, donc je fais une boucle dans les propriétés de l'objet de filtre et je le vérifie:

function filterUsers (users, filter) {
    var result = [];
    for (var prop in filter) {
        if (filter.hasOwnProperty(prop)) {

            //at the first iteration prop will be address
            for (var i = 0; i < filter.length; i++) {
                if (users[i][prop] === filter[prop]) {
                    result.push(users[i]);
                }
            }
        }
    }
    return result;
}

Donc lors de la première itération quand {[3] } sera égal 'England' deux utilisateurs seront ajoutés au résultat du tableau (avec le nom Tom et Mark), mais lors de la deuxième itération quand {[5] } sera égal Mark seul le dernier utilisateur devrait être ajouté au résultat du tableau, mais je me retrouve avec deux éléments dans le tableau.

J'ai une petite idée de pourquoi cela se passe-t-il mais toujours coincé dessus et n'a pas pu trouver une bonne solution pour le réparer. Toute aide est appréciable. Grâce.

22
demandé sur Prerna Jain 2015-08-05 14:47:42

7 réponses

, Vous pouvez faire comme ceci

var filter = {
  address: 'England',
  name: 'Mark'
};
var users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    age: 28,
    address: 'England'
  }
];


users= users.filter(function(item) {
  for (var key in filter) {
    if (item[key] === undefined || item[key] != filter[key])
      return false;
  }
  return true;
});

console.log(users)
36
répondu Raghavendra 2018-04-06 18:39:24

Une autre prise pour ceux d'entre vous qui aiment le code succinct.

NOTE : la méthode FILTER peut prendre un argument supplémentaire this, puis en utilisant une fonction de flèche E6, nous pouvons réutiliser le bon this pour obtenir un bon one-liner.

var users = [{name: 'John',email: 'johnson@mail.com',age: 25,address: 'USA'},
             {name: 'Tom',email: 'tom@mail.com',age: 35,address: 'England'},
             {name: 'Mark',email: 'mark@mail.com',age: 28,address: 'England'}];

var query = {address: "England", name: "Mark"};

var result = users.filter(search, query);

function search(user){
  return Object.keys(this).every((key) => user[key] === this[key]);
}




// |----------------------- Code for displaying results -----------------|
var element = document.getElementById('result');

function createMarkUp(data){
  Object.keys(query).forEach(function(key){
    var p = document.createElement('p');
    p.appendChild(document.createTextNode(
    key.toUpperCase() + ': ' + result[0][key]));
    element.appendChild(p);
  });
}

createMarkUp(result);
<div id="result"></div>
7
répondu SoEzPz 2017-11-20 15:14:18

Vous pouvez le faire dans une ligne

users = users.filter(obj => obj.name == filter.name && obj.address == filter.address)
2
répondu Abhishek 2018-02-26 18:41:44

Je pense que cela pourrait aider.

const filters = ['a', 'b'];

const results = [
  {
    name: 'Result 1',
    category: ['a']
  },
  {
    name: 'Result 2',
    category: ['a', 'b']
  },
  {
    name: 'Result 3',
    category: ['c', 'a', 'b', 'd']
  }
];

const filteredResults = results.filter(item =>
  filters
    .map(val => item.category.indexOf(val))
    .map(val => (val > -1 ? true : false))
    .reduce((acc, cum) => acc && cum)
);

console.log(filteredResults);
  
1
répondu Coşkun Deniz 2017-06-27 20:51:09

Peut également être fait de cette façon:

    this.users = this.users.filter((item) => {
                return (item.name.toString().toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.address.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.age.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.email.toLowerCase().indexOf(val.toLowerCase()) > -1);
            })
1
répondu Diogo Rodrigues 2018-03-20 19:55:41

Si la finalité de votre code est d'obtenir l'utilisateur filtré, j'inverserais le for pour évaluer le user au lieu de réduire le tableau de résultats à chaque itération.

Voici un exemple (non testé):

function filterUsers (users, filter) {
    var result = [];

    for (i=0;i<users.length;i++){
        for (var prop in filter) {
            if (users.hasOwnProperty(prop) && users[i][prop] === filter[prop]) {
                result.push(users[i]);
            }
        }
    }
    return result;
}
0
répondu The_Black_Smurf 2015-08-05 11:56:51

Voici la version ES6 de l'utilisation de la fonction flèche dans le filtre. Poster ceci comme une réponse parce que la plupart d'entre nous utilisent ES6 ces jours-ci et peuvent aider les lecteurs à filtrer de manière avancée en utilisant la fonction arrow, let et const.

const filter = {
  address: 'England',
  name: 'Mark'
};
let users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    age: 28,
    address: 'England'
  }
];


users= users.filter(item => {
  for (let key in filter) {
    if (item[key] === undefined || item[key] != filter[key])
      return false;
  }
  return true;
});

console.log(users)
0
répondu Think-Twice 2018-09-06 06:58:27