filtrarea unui array în JavaScript cu condiții multiple


Vreau să simplific un tablou de obiecte. Să presupunem că am următorul tablou:

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

Și obiectul filtru:

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

De exemplu, trebuie să filtrez toți utilizatorii după adresă și nume, așa că parcurg în buclă proprietățile obiectului de filtrare și verific:

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;
}

Deci, în timpul primei iterații, când prop - address va fi egal cu 'England', doi utilizatori vor fi adăugați în array-ul rezultat (cu numele Tom și Mark), dar la a doua iterație, când prop name va fi egal cu Mark, doar ultimul utilizator ar trebui să fie adăugat în array-ul rezultat, însă ajung cu două elemente în array.

Am o mică idee despre de ce se întâmplă, dar totuși sunt blocat și nu am reușit să găsesc o soluție bună pentru a rezolva problema. Orice ajutor este apreciat. Mulțumesc.

Răspuns #1

Poți să faci așa

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

Răspunsul #2

Dacă știi numele filtrelor, poți să o faci într-o linie.

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

Răspunsul #3

O altă variantă pentru cei dintre voi care apreciază codul succint.

NOTĂ: Metoda FILTER poate lua un argument suplimentar this, apoi folosind o funcție săgeată E6 putem reutiliza this corect pentru a obține o expresie scurtă elegantă.

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

Răspunsul #4

users.filter(o => o.address == 'England' && o.name == 'Mark')

Mult mai bine pentru es6. Sau poți folosi operatorul || (sau) astfel

users.filter(o => {return (o.address == 'England' || o.name == 'Mark')})

Răspunsul #5

Iată versiunea ES6 de utilizare a funcției săgeată în filter. Postez acest lucru ca răspuns deoarece majoritatea dintre noi folosim ES6 în zilele noastre și poate ajuta cititorii să folosească filter într-un mod avansat folosind funcția săgeată, let și const.

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

Răspunsul #6

Folosind Array.Filter() cu Funcții săgeată putem realiza acest lucru folosind

users=users.filter(x => x.name == 'Mark' && x.address == 'England');

Iată fragmentul complet

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

//filtering the users array and saving 
//result back in users variable
users = users.filter(x => x.name == 'Mark' && x.address == 'England');


//logging out the result in console
console.log(users);

Răspunsul #7

Îmbunătățind răspunsurile bune de aici, mai jos este soluția mea:

const rawData = [
  { name: 'John', email: '[email ', age: 25, address: 'USA' },
  { name: 'Tom', email: '[email ', age: 35, address: 'England' },
  { name: 'Mark', email: '[email ', age: 28, address: 'England' }
]
const filters = { address: 'England', age: 28 }

const filteredData = rawData.filter(i =>
  Object.entries(filters).every(([k, v]) => i[k] === v)
)

Răspunsul #8

Se poate face și în acest fel:

    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);
            })