2012-05-30 21 views
5

Ich habe ein Array von event Objekte namens events. Jedes event hat markets, ein Array, das market Objekte enthält. Darin befindet sich ein weiteres Array namens outcomes, das outcome Objekte enthält.Underscore.js .filter() und .any()

In this question, ich fragte nach einem [Underscore.js] Weg, um alle Ereignisse zu finden, die Märkte haben, die Ergebnisse haben, die eine Eigenschaft mit dem Namen test haben. Die Antwort war:

// filter where condition is true 
_.filter(events, function(evt) { 

    // return true where condition is true for any market 
    return _.any(evt.markets, function(mkt) { 

     // return true where any outcome has a "test" property defined 
     return _.any(mkt.outcomes, function(outc) { 
      return outc.test !== "undefined" && outc.test !== "bar"; 
     }); 
    }); 
}); 

Dies funktioniert gut, aber ich frage mich, wie ich es ändern würde, wenn ich die Ergebnisse für jeden Markt, so dass market.outcomes nur gespeicherten Ergebnisse, die waren gleich bar filtern will. Derzeit gibt mir dies nur Märkte, die Ergebnisse haben, die einigetest Eigenschaften gesetzt haben. Ich möchte diejenigen ausstreifen, die das nicht tun.

+0

Ist es wirklich toll funktioniert? Ihr innerster '.any()' Callback verweist auf "outcome", aber der Parameter ist "outc" ... – Pointy

+0

Außerdem scheint es, als ob Sie nur von '.any()' zu '.all() wechseln müssen. 'mit einer entgegengesetzten Bedingung. Mit anderen Worten, gehen Sie von "alle, die sind ..." zu "alle, die nicht ... sind" – Pointy

+0

Sorry, Tippfehler .... –

Antwort

5

es eine einfache Schleife Stellen, die splice method für die Array-umzug mit:

var events = [{markets:[{outcomes:[{test:x},...]},...]},...]; 
for (var i=0; i<events.length; i++) { 
    var mrks = events[i].markets; 
    for (var j=0; j<mrks.length; j++) { 
     var otcs = mrks[j].outcomes; 
     for (var k=0; k<otcs.length; k++) { 
      if (! ("test" in otcs[k])) 
       otcs.splice(k--, 1); // remove the outcome from the array 
     } 
     if (otcs.length == 0) 
      mrks.splice(j--, 1); // remove the market from the array 
    } 
    if (mrks.length == 0) 
     events.splice(i--, 1); // remove the event from the array 
} 

Dieser Code alle Ergebnisse entfernen, die keine test Eigenschaft haben, alle leeren Märkte und alle leeren Ereignisse aus dem events Array.

Eine Unders Version könnte so aussehen:

events = _.filter(events, function(evt) { 
    evt.markets = _.filter(evt.markets, function(mkt) { 
     mkt.outcomes = _.filter(mkt.outcomes, function(otc) { 
      return "test" in otc; 
     }); 
     return mkt.outcomes.length > 0; 
    }); 
    return evt.markets.length > 0; 
}); 
+0

Super, danke. Kann dies jedoch mit Underscore erreicht werden (da ich die Bibliothek bereits anderweitig verwende und der Code wahrscheinlich viel besser lesbar wäre). –

+0

Ja, es ist möglich. Die Unterstreichungsfilterfunktion erstellt jedoch neue Array-Instanzen, die dann die veralteten Arrays überschreiben, anstatt nur Elemente aus ihnen zu löschen. – Bergi

+0

@bergi Nichts ist falsch, wenn Daten nicht mutiert werden – Kloar