2012-05-30 21 views
5

Tengo una matriz de event objetos llamados events. Cada event tiene markets, una matriz que contiene market objetos. Dentro de aquí hay otra matriz llamada outcomes, que contiene outcome objetos.Underscore.js .filter() y .any()

En this question, solicité una forma [Underscore.js] para encontrar todos los eventos que tienen mercados que tienen resultados que tienen una propiedad llamada test. La respuesta fue:

// 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"; 
     }); 
    }); 
}); 

Esto funciona muy bien, pero me pregunto cómo iba a alterarla si quería filtrar los resultados para cada mercado, por lo que sólo se market.outcomes resultados almacenados que eran iguales a bar. Actualmente, esto solo me está dando mercados que tienen resultados que tienen algunas propiedades detest. Quiero quitar los que no.

+0

funciona realmente grande? La devolución de llamada '.any()' más interna hace referencia al "resultado" pero el parámetro es "outc" ... – Pointy

+0

Además, aparte de eso, parece que solo necesitas voltear de '.any()' a '.all() 'con una condición opuesta. En otras palabras, vaya de "cualquiera que sea ..." a "todo lo que no sea ..." – Pointy

+0

Lo sentimos, error de tipe ... –

Respuesta

5

lo convierten en un bucle simple, utilizando la splice method para las absorciones de matriz:

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 
} 

Este código eliminará todos los resultados que no tienen test propiedad, todos los mercados vacíos y todos los eventos vacíos de la matriz events.

versión

un guión podría parecerse a lo siguiente:

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

Impresionante, gracias. Sin embargo, esto se puede lograr con Underscore (ya que ya estoy usando la biblioteca en otro lado y el código probablemente sea mucho más legible). –

+0

Sí, es posible. Pero la función de filtro de subrayado crea nuevas instancias de matriz, que luego sobrescribirán las matrices obsoletas, en lugar de simplemente eliminar elementos de ellas. – Bergi

+0

@bergi No hay nada de malo en no mutar los datos – Kloar