什么是underscore.js相当于LINQ的SelectMany运算符?
想象一下,我有一个嵌套的数组结构。
var nested = [ [1], [2], [3] ];
使用underscore.js ,我将如何产生一个平坦的数组?
在C#中,你会使用Enumerable.SelectMany
像这样:
var flattened = nested.SelectMany(item => item);
请注意,在这种情况下,lambda直接select嵌套的项目,但它可以是任何任意的expression式。
在jQuery中,可以使用:
var flattened = $.map(nested, function(item) { return item; });
但是,这种方法不适用于下划线的地图function。
那么如何使用underscore.js得到扁平数组[1, 2, 3]
?
var nested = [ [1], [2], [3] ]; var flattened = _.flatten(nested);
这里是一个小提琴
如果你有一个稍微复杂的数组,比如来自JSON的数组,你可以利用pluck方法,提取你感兴趣的特定属性,类似于parents.SelectMany(parent => parent.Items);
// underscore version var allitems = _.flatten(_.pluck(parents, 'items'));
现在所有的项目都是来自父母[a,b,c,d]
的所有子项目的排列。
和一个JSFiddle显示相同的事情。
或者,如果您使用lodash,则可以使用自版本4以来可用的_.flatMap函数执行同样的操作。Cred to Noel用于在注释中指出它。
var parents = [ { name: 'hello', items: ['a', 'b'] }, { name: 'world', items: ['c', 'd'] } ]; // version 1 of lodash, straight up var allitems = _.flatMap(parents, 'items'); logIt('straight', allitems); // or by wrapping the collection first var allitems = _(parents) .flatMap('items') .value(); logIt('wrapped', allitems); // this basically does _(parents).map('items').flatten().value(); function logIt(wat, value) { document.getElementById('result').innerHTML += wat + ':' + JSON.stringify(value) + '\r\n<br/>'; }
<script src="lodash/4.16.6/lodash.min.js"></script> <div id="result"></div>
我们也可以把Patrick的解决scheme变成一个mixin,使它变成可链接的:
_.mixin({ selectMany: function(collection, iteratee=_.identity) { return _.flatten(_.map(collection, iteratee)); } });
例子:
let sample = [{a:[1,2],b:'x'},{a:[3,4],b:'y'}]; console.log(_.selectMany(sample, 'a')); // [ 1, 2, 3, 4 ] console.log(_.chain(sample).selectMany(o => oa).filter(a => a % 2 === 0).map(a => a * 3).value()); // [ 6, 12 ]
我在lodash里找不到任何和SelectMany
很像的方法,所以我用纯JS创build了一个:
Array.prototype.selectMany = function(fn) { return Array.prototype.concat(...this.map(fn)); };
繁荣。
> console.log([{a:[1,2],b:'x'},{a:[3,4],b:'y'}].selectMany(o => oa)); [ 1, 2, 3, 4 ]