什么是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); 

这里是一个小提琴

如果你有一个稍微复杂的数组,比如来自J​​SON的数组,你可以利用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 ]