Let me explain more:
we know that map function in jQuery acts as .Select() (as in LINQ).
$("tr").map(function() { return $(this).children().first(); }); // returns 20开发者_开发技巧 tds
now the question is how can we have .SelectMany() in jQuery?
$("tr").map(function() { return $(this).children(); }); // returns 10 arrays not 20 tds!
here is my example in action: http://jsfiddle.net/8aLFQ/4/
"l2" should be 8 if we have selectMany.[NOTE] please don't stick to this example, above code is to just show what I mean by SelectMany() otherwise it's very easy to say $("tr").children();
Hope it's clear enough.
map
will flatten native arrays. Therefore, you can write:
$("tr").map(function() { return $(this).children().get(); })
You need to call .get()
to return a native array rather than a jQuery object.
This will work on regular objects as well.
var nested = [ [1], [2], [3] ];
var flattened = $(nested).map(function() { return this; });
flattened
will equal [1, 2, 3]
.
You want this:
$("tr").map(function() { return $(this).children().get(); });
Live demo: http://jsfiddle.net/8aLFQ/12/
You're going to kick yourself:
$("tr").map(function() { return [ $(this).children() ]; });
It's the simple things in life you treasure. -- Fred Kwan
EDIT: Wow, that will teach me to not to test answers thoroughly.
The manual says that map
flattens arrays, so I assumed that it would flatten an array-like object. Nope, you have to explicit convert it, like so:
$("tr").map(function() { return $.makeArray($(this).children()); });
Things should be as simple as possible, but no simpler. -- Albert Einstein
$.map
expects a value (or an array of values) returned. The jQuery object you are returning is being used as a "value" instead of an "array" (which get flattened)
All you need to do is return the array of DOM elements. jQuery provides a .get()
method that returns a plain array from a selection.
$("tr").map(function() { return $(this).children().get() });
Of course, I understand this is a very contrived example, since $("tr").children()
does the same thing with a lot less function calls.
http://jsfiddle.net/gnarf/8aLFQ/13/
I had the same question for regular arrays, and this is the only reference I could find in StackOverflow, so I'll add the answer I came up with.
For regular arrays, you can use
Array.prototype.selectMany = function (selector) {
return this.map(selector).reduce(function (a, b) {
return a.concat(b);
});
};
Thus [[1, 2], [3, 4], [5, 6, 7]].selectMany(function (a) { return a; })
evaluates to [1, 2, 3, 4, 5, 6, 7]
.
To use this in jQuery, you have to convert your jQuery set into an array before using it:
var result = $("tr").get().selectMany(function(a) {
return Array.prototype.slice.call(a.childNodes);
});
Not sure about .selectMany()
but you could change the position of .children
to get the desired result.
var l2 = $("tr").children().map(function() { return $(this); }).length;
http://jsfiddle.net/8aLFQ/5/
EDIT
I think I better understand what you're after following the comments.
You can call $.makeArray(l2)
to return what you are after... that is 8 objects/arrays
http://jsfiddle.net/8aLFQ/10/
精彩评论