2011-07-25 15 views
34

Déjame explicarte más:¿Qué función actúa como .SelectMany() en jQuery?

sabemos que la función de mapa en jQuery actúa como .Select() (como en LINQ).

$("tr").map(function() { return $(this).children().first(); }); // returns 20 tds 

ahora la pregunta es ¿cómo podemos tener .SelectMany() en jQuery?

$("tr").map(function() { return $(this).children(); }); // returns 10 arrays not 20 tds! 

aquí está mi ejemplo en acción: http://jsfiddle.net/8aLFQ/4/
"L2" debe ser de 8 si tenemos SelectMany.

[NOTA] por favor, no se adhiera a este ejemplo, el código anterior es simplemente mostrar lo que quiero decir con SelectMany() de lo contrario, es muy fácil decir $ ("tr"). Children();

Espero que sea lo suficientemente claro.

Respuesta

43

map apilará matrices nativas. Por lo tanto, se puede escribir:

$("tr").map(function() { return $(this).children().get(); }) 

Es necesario llamar .get() a devolver una matriz nativa en lugar de un objeto jQuery.

Esto funcionará en objetos comunes también.

var nested = [ [1], [2], [3] ]; 
var flattened = $(nested).map(function() { return this; }); 

flattened será igual [1, 2, 3].

+0

@ Šime Vidas - sí, eso sucede cuando no * publico * * dos * respuestas inferiores primero. "Siempre estoy listo para aprender, aunque no siempre me gusta que me enseñen". - Winston Churchill – Malvolio

1

No estoy seguro acerca de .selectMany() pero podría cambiar la posición de .children para obtener el resultado deseado.

var l2 = $("tr").children().map(function() { return $(this); }).length; 

http://jsfiddle.net/8aLFQ/5/

EDITAR

creo que entiendo mejor lo que está después de seguir los comentarios.

Puede llamar $.makeArray(l2) para devolver lo que está después ... es decir 8 objetos/matrices

http://jsfiddle.net/8aLFQ/10/

+0

¿Por qué necesito un mapa entonces? eso es solo un ejemplo para mostrar lo que quiero decir con SelectMany() –

+0

No creo que eso sea lo que el OP estaba pidiendo en absoluto. Lo que él quería (creo) es una versión de 'map' que no aplana las listas. (Editar: OP parece estar de acuerdo. @valipour: ver mi respuesta, arriba) – Malvolio

5

vas a patear a ti mismo:

$("tr").map(function() { return [ $(this).children() ]; }); 

Es las cosas simples de la vida que atesoras. - Fred Kwan

EDITAR: Vaya, que me va a enseñar a no ensayar respuestas a fondo.

El manual dice que map aplana las matrices, así que supuse que aplanaría un objeto tipo array. No, usted tiene que convertir explícita que, de este modo:

$("tr").map(function() { return $.makeArray($(this).children()); }); 

Las cosas deben ser tan simple como sea posible, pero no más simple. - Albert Einstein

+0

Esto obviamente no seleccionará los 20 elementos TD (que es lo que quiere el OP). –

+0

¿logró ejecutar en jsFiddle? Todavía tengo 2! - ¡Este no es el candidato! –

+0

Esto no funciona. – SLaks

4

$.map espera un valor (o una matriz de valores) devueltos. El objeto jQuery que está devolviendo se está utilizando como un "valor" en lugar de una "matriz" (que se aplana)

Todo lo que necesita hacer es devolver la matriz de elementos DOM. jQuery proporciona un método .get() que devuelve una matriz simple de una selección.

$("tr").map(function() { return $(this).children().get() }); 

Por supuesto, entiendo que esto es un ejemplo muy artificial, ya que $("tr").children() hace lo mismo con muchas menos llamadas a funciones.

http://jsfiddle.net/gnarf/8aLFQ/13/

1

que tenían la misma pregunta para las matrices regulares, y esta es la única referencia que pude encontrar en stackoverflow, así que añadiremos la respuesta que se me ocurrió.

Para las matrices regulares, puede utilizar

Array.prototype.selectMany = function (selector) { 
    return this.map(selector).reduce(function (a, b) { 
     return a.concat(b); 
    }); 
}; 

Así [[1, 2], [3, 4], [5, 6, 7]].selectMany(function (a) { return a; }) evalúa a [1, 2, 3, 4, 5, 6, 7].

Para utilizar esto en jQuery, usted tiene que convertir su conjunto de jQuery en una matriz antes de usarlo:

var result = $("tr").get().selectMany(function(a) { 
    return Array.prototype.slice.call(a.childNodes); 
}); 
Cuestiones relacionadas