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.
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)
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>
Vous pouvez le faire en ligne
users = users.filter(obj => obj.name == filter.name && obj.address == filter.address)
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);
})
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)
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);
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;
}
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
);
}