Je souhaite parcourir un tableau d'objets pour créer un nouveau tableau filtré. Mais aussi, j'ai besoin de filtrer certains des objets du nouveau tableau en fonction d'un paramètre. J'essaye ceci:
function renderOptions(options) {
return options.map(function (option) {
if (!option.assigned) {
return (someNewObject);
}
});
}
Est-ce une bonne approche? Y a-t-il une meilleure méthode? Je suis ouvert à utiliser n'importe quelle bibliothèque telle que lodash.
Vous devriez utiliser Array.reduce
pour cela.
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = options.reduce(function(filtered, option) {
if (option.assigned) {
var someNewValue = { name: option.name, newProperty: 'Foo' }
filtered.Push(someNewValue);
}
return filtered;
}, []);
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>
Plus d'infos: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Utilisez réduire, Luke!
function renderOptions(options) {
return options.reduce(function (res, option) {
if (!option.assigned) {
res.Push(someNewObject);
}
return res;
}, []);
}
Une ligne reduce
avec ES6 fancy syntaxe répandue est ici!
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
const filtered = options
.reduce((result, {name, assigned}) => [...result, ...assigned ? [name] : []], []);
console.log(filtered);
Utilisez Array.prototype.filter même
function renderOptions(options) {
return options.filter(function(option){
return !option.assigned;
}).map(function (option) {
return (someNewObject);
});
}
Array.prototype.flatMap est une autre option.
const options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
options.flatMap(o => o.assigned && o.name || []);
// ['One', 'Three']
De la page MDN liée ci-dessus:
flatMap
peut être utilisé pour ajouter et supprimer des éléments (modifier le nombre d'éléments) au cours d'une carte. En d'autres termes, cela vous permet de mapper de nombreux éléments sur de nombreux éléments (en traitant chaque élément d'entrée séparément), plutôt que toujours un à un. En ce sens, cela fonctionne comme le contraire du filtre. Renvoyez simplement un tableau à 1 élément pour conserver l'élément, un tableau à plusieurs éléments pour ajouter des éléments ou un tableau à 0 éléments pour supprimer l'élément.
J'ai optimisé les réponses avec les points suivants:
if (cond) { stmt; }
en cond && stmt;
Je présenterai deux solutions, l'une utilisant pourChaque , l'autre utilisant réduire :
Solution 1: Utiliser forEach
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = []
options.forEach(o => {
o.assigned && reduced.Push( { name: o.name, newProperty: 'Foo' } );
} );
console.log(reduced);
Solution 2: Utiliser réduire
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = options.reduce((a, o) => {
o.assigned && a.Push( { name: o.name, newProperty: 'Foo' } );
return a;
}, [ ] );
console.log(reduced);
Je vous laisse le soin de décider quelle solution choisir.
À l’aide de réduction, vous pouvez le faire dans une fonction Array.prototype. Cela va chercher tous les nombres pairs d'un tableau.
var arr = [1,2,3,4,5,6,7,8];
var brr = arr.reduce(function(c,n){
if(n%2!=0){
return c;
}
c.Push(n);
return c;
},[]);
document.getElementById('mypre').innerHTML = brr.toString();
<h1>Get all even numbers</h1>
<pre id="mypre"> </pre>
Vous pouvez utiliser la même méthode et la généraliser pour vos objets, comme ceci.
var arr = options.reduce(function(c,n){
if(somecondition){return c;}
c.Push(n); return c;
},[]);
arr
va maintenant contenir les objets filtrés.
Je ferais un commentaire, mais je n'ai pas la réputation requise. Une petite amélioration à la très bonne réponse de Maxim Kuzmin pour le rendre plus efficace:
const options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
const filtered = options
.reduce((result, { name, assigned }) => assigned ? result.concat(name) : result, []);
console.log(filtered);
Explication
Au lieu de répéter le résultat entier à chaque itération, nous ajoutons uniquement au tableau, et uniquement lorsqu'il existe une valeur à insérer.
À un moment donné, n’est-il pas plus facile (ou tout aussi facile) d’utiliser une variable forEach
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = []
options.forEach(function(option) {
if (option.assigned) {
var someNewValue = { name: option.name, newProperty: 'Foo' }
reduced.Push(someNewValue);
}
});
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>
Cependant, ce serait bien s'il y avait une fonction malter()
ou fap()
qui combine les fonctions map
et filter
. Cela fonctionnerait comme un filtre, sauf qu'au lieu de retourner vrai ou faux, cela retournerait n'importe quel objet ou un null/undefined.