Mapper et filtrer un tableau en même temps en Javascript

J'ai un tableau d'objets que je veux parcourir pour produire un nouveau filtré tableau. Mais aussi, j'ai besoin de filtrer certains des objets du nouveau tableau en fonction d'un paramètre. J'essaie ceci:

function renderOptions(options) {
    return options.map(function (option) {
        if (!option.assigned) {
            return (someNewObject);
        }
    });   
}

Est-ce une bonne approche? Est-il une meilleure méthode? Je suis ouvert à utiliser n'importe quelle bibliothèque telle que lodash.

50
demandé sur thefourtheye 2015-12-21 17:43:13

8 réponses

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'Informations: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

69
répondu thefourtheye 2017-07-03 18:06:28

Utiliser réduire, Luke!

function renderOptions(options) {
    return options.reduce(function (res, option) {
        if (!option.assigned) {
            res.push(someNewObject);
        }
        return res;
    }, []);   
}
31
répondu Zuker 2015-12-21 14:52:21

Une ligne reduce avec ES6 fantaisie propagation de la syntaxe, c'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);
5
répondu Maxim Kuzmin 2018-04-26 13:22:29

Avec ES6 vous pouvez le faire très court:

options.filter(opt => !opt.assigned).map(opt => someNewObject)

4
répondu Natividad Lara Diaz 2017-06-14 11:59:19

Utiliser Tableau.prototype.filtre lui-même

function renderOptions(options) {
    return options.filter(function(option){
        return !option.assigned;
    }).map(function (option) {
        return (someNewObject);
    });   
}
1
répondu AmmarCSE 2015-12-21 14:45:08

En utilisant reduce, vous pouvez le faire dans un tableau.prototype de la fonction. Cela récupérera 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 contient maintenant les objets filtrés.

1
répondu Bhargav Ponnapalli 2015-12-21 14:52:34

J'ai optimisé les réponses avec les points suivants:

  1. réécrire if (cond) { stmt; } comme cond && stmt;
  2. Utiliser ES6 Flèche Fonctions

Je vais présenter deux solutions, l'une en utilisant forEach, l'autre en utilisant reduce :

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: Utilisation de 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 décider quelle solution choisir.

1
répondu Stephen Quan 2017-11-30 00:03:17

À un moment donné, n'est-il pas plus facile(ou tout aussi facile) d'utiliser un 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 renvoyer true ou false, il retournerait n'importe quel objet ou un null/undefined.

0
répondu Daniel 2017-11-17 17:54:29