web-dev-qa-db-fra.com

javascript filter array plusieurs conditions

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

var users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
    },
    {
        name: 'Tom',
        email: '[email protected]',
        age: 35,
        address: 'England'
    },
    {
        name: 'Mark',
        email: '[email protected]',
        age: 28,
        address: 'England'
}];

Et objet filtre:

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

Par exemple, j'ai besoin de filtrer tous les utilisateurs par adresse et par nom. Je passe donc en boucle dans les propriétés des objets filtres et les 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;
}

Ainsi, lors de la première itération, lorsque prop - address 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, lorsque prop name sera égal à Mark, seul le dernier utilisateur devra être ajouté au résultat du tableau. se retrouver avec deux éléments dans un tableau. 

J'ai une petite idée de la raison pour laquelle cela se produit mais qui reste bloqué dessus et ne peut pas trouver une bonne solution pour le réparer. Toute aide est appréciable. Merci.

28
user3673623

Tu peux faire comme ça

var filter = {
  address: 'England',
  name: 'Mark'
};
var users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: '[email protected]',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: '[email protected]',
    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)

45
Raghavendra

Une autre prise pour ceux qui aiment le code succinct.

NOTE: La méthode FILTRE 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 Nice doublure.

var users = [{name: 'John',email: '[email protected]',age: 25,address: 'USA'},
             {name: 'Tom',email: '[email protected]',age: 35,address: 'England'},
             {name: 'Mark',email: '[email protected]',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>

11
SoEzPz

Vous pouvez le faire en ligne

users = users.filter(obj => obj.name == filter.name && obj.address == filter.address)
9
Abhishek

Peut aussi ê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);
            })
5
Diogo Rodrigues

Voici la version ES6 de l'utilisation de la fonction de flèche dans le filtre. En publiant ceci comme réponse, car la plupart d’entre nous utilisons ES6 de nos jours et peuvent aider les lecteurs à filtrer de manière avancée à l’aide de la fonction flèche, let et const. 

const filter = {
  address: 'England',
  name: 'Mark'
};
let users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: '[email protected]',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: '[email protected]',
    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)

4
Hemadri Dasari

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
Coşkun Deniz

Si la finalité de votre code est d'obtenir l'utilisateur filtré, je voudrais inverser la for pour évaluer la 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
The_Black_Smurf

avec la composition de quelques petits assistants:

const filter = {address: 'England', name: 'Mark'};
console.log( 
  users.filter(and(map(propMatches)(filter)))
)

function propMatches<T>(property: string, value: any) {
  return (item: T): boolean => item[property] === value
}

function map<T>(mapper: (key: string, value: any, obj: T) => (item:T) => any) {
  return (obj: T) => {
    return Object.keys(obj).map((key) => {
      return mapper(key, obj[key], obj)
    });
  }
}

export function and<T>(predicates: ((item: T) => boolean)[]) {
  return (item: T) =>
    predicates.reduce(
        (acc: boolean, predicate: (item: T) => boolean) => {
            if (acc === undefined) {
                return !!predicate(item);
            }
            return !!predicate(item) && acc;
        },
        undefined // initial accumulator value
    );
}
0
nils petersohn