2015-12-21 10 views
26

Ich habe ein Array von Objekten, die ich durchlaufen, um ein neues gefiltertes Array zu erzeugen. Aber auch, ich muss einige der Objekte aus dem neuen Array abhängig von einem Parameter herausfiltern. Ich versuche das:Map und Filter ein Array zur gleichen Zeit in Javascript

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

Ist das ein guter Ansatz? Gibt es eine bessere Methode? Ich bin offen, irgendeine Bibliothek wie lodash zu benutzen.

+0

Was ist mit einem "object.keys" -Ansatz? https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/keys – Julo0sS

+0

Verwenden Sie reduzieren: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/reduce –

Antwort

39

sollten Sie Array.reduce für diese.

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>

Weitere Informationen: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

+0

Für mich ist das erste Argument "gefiltert" ein Objekt. so ist 'filtered.push' für mich undefiniert. –

+0

Ich hatte auch ein Problem mit "gefiltert" als ein Objekt. Dies liegt daran, dass ich den "Initialwert" - das leere Array ('[]') nach der Reduce-Funktion nicht übergeben habe. z.B. falsche 'var reduziert = options.reduce (function (gefiltert Option) { ... });' richtig 'var reduziert = options.reduce (function (gefiltert, Option) { .. }, []); ' –

1

Verwenden Array.prototy.filter selbst

function renderOptions(options) { 
    return options.filter(function(option){ 
     return !option.assigned; 
    }).map(function (option) { 
     return (someNewObject); 
    }); 
} 
+0

Dies beantwortet nichts. Die Frage ist, wie wir die beiden Array-Funktionen zu einer vereinfachen. –

28

Verwendung reduzieren, Luke!

function renderOptions(options) { 
    return options.reduce(function (res, option) { 
     if (!option.assigned) { 
      res.push(someNewObject); 
     } 
     return res; 
    }, []); 
} 
1

Mit reduce können Sie dies in einer Array.prototype-Funktion tun. Dies wird alle geraden Zahlen von einem Array abrufen.

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>

können Sie die gleiche Methode verwenden und verallgemeinern es für Ihre Objekte, wie diese.

arr enthält jetzt die gefilterten Objekte.

2

Mit ES6 können Sie es sehr kurz:

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

+0

Dies führt zu zwei Loops, je nachdem, welche Filter Returns noch Speicher auffressen können. – hogan

0

An einem gewissen Punkt ist es nicht einfacher (oder einfach nur so einfach) zu verwenden, um ein 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>

Es wäre aber nett, wenn es eine malter() odergäbeFunktion, die die map und filter Funktionen kombiniert. Es würde wie ein Filter funktionieren, außer dass es statt true oder false ein beliebiges Objekt oder ein null/undefined zurückgibt.

0

optimiert ich die Antworten mit den folgenden Punkten:

  1. if (cond) { stmt; } als cond && stmt;
  2. Verwenden ES6 Arrow Functions

Umschreiben werde ich zwei Lösungen präsentieren, ein forEach verwendet, das andere mit reduce :

Solut Ion 1: Verwendung 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);

Lösung 2:

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

reduzieren Verwenden ich es verlassen, um Ihnen zu entscheiden, welche Lösung gehen Sie für.

+0

Warum in aller Welt würden Sie 'cond & & stmt;' verwenden? Dies ist viel schwieriger zu lesen und bietet keinerlei Vorteile. – jlh

Verwandte Themen