javascript 与 LINQ 的 SelectMany 运算符等效的 underscore.js 是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12344007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:59:09  来源:igfitidea点击:

What's the underscore.js equivalent to LINQ's SelectMany operator?

javascriptunderscore.jslinq

提问by Drew Noakes

Imagine I have a nested array structure.

想象一下我有一个嵌套的数组结构。

var nested = [ [1], [2], [3] ];

Using underscore.js, how would I produce a flattened array?

使用underscore.js,我将如何生成扁平数组?

In C# you would use Enumerable.SelectManylike this:

在 C# 中,你会Enumerable.SelectMany像这样使用:

var flattened = nested.SelectMany(item => item);

Note that the lambda in this case selects the nested item directly, but it could have been any arbitrary expression.

请注意,本例中的 lambda 直接选择嵌套项,但它可以是任何任意表达式。

In jQuery, it's possible to just use:

在 jQuery 中,可以只使用:

var flattened = $.map(nested, function(item) { return item; });

However this approach doesn't work with underscore's mapfunction.

然而,这种方法不适用于下划线的地图功能。

So how would I get the flattened array [1, 2, 3]using underscore.js?

那么如何[1, 2, 3]使用 underscore.js获得扁平化的数组呢?

采纳答案by armen.shimoon

var nested = [ [1], [2], [3] ];
var flattened = _.flatten(nested);

Heres a fiddle

这是一把小提琴

回答by Patrick

If you have a slightly more complicated array, say one coming from JSON, you can take advantage of the pluckmethod as well, extracting the specific property you are interested in, similar to parents.SelectMany(parent => parent.Items);

如果您有一个稍微复杂一点的数组,比如说一个来自 JSON 的数组,您也可以利用pluck方法,提取您感兴趣的特定属性,类似于parents.SelectMany(parent => parent.Items);

// underscore version
var allitems = _.flatten(_.pluck(parents, 'items'));

allitemsis now the array of all subitems from the parents, [a,b,c,d].

allitems现在是来自父项的所有子项的数组,[a,b,c,d]

And a JSFiddleshowing the same thing.

还有一个JSFiddle显示了同样的事情。



Or, if you are using lodash you can do the same thing by using the _.flatMapfunction which is available since version 4. Cred to Noel for pointing it out in the comments.

或者,如果您正在使用 lodash,您可以使用_.flatMap函数来做同样的事情,该函数自版本 4 起可用。感谢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) {
  console.log(wat, value)
}
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script>
<pre id="result"></pre>



In case you want to do more stuff and don't want to chain operators, you can use the flowfunction to get the same effect. This is useful if you are using TypeScript and importing each operator individually, since you can then optimize your final payload.

如果您想做更多的事情并且不想链接运算符,您可以使用该flow函数来获得相同的效果。如果您使用 TypeScript 并单独导入每个运算符,这将非常有用,因为您可以优化最终的有效负载。

const parents = [
  { name: 'hello', items: ['a', 'b'] },
  { name: 'world', items: ['c', 'd'] }
];
logIt('original', parents);

const result = _.flow(
  (collection) => _.flatMap(collection, (item) => item.items),
  (flattened) => flattened.filter((item) => item !== 'd')
)(parents);
logIt('result without "d"', result);

function logIt(wat, value) {
  console.log(wat, value);
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<pre id="result"></pre>

回答by mpen

We can also make Patrick's solutioninto a mixin so that it becomes chainable:

我们还可以将Patrick 的解决方案变成一个 mixin,以便它变得可链接:

_.mixin({
    selectMany: function(collection, iteratee=_.identity) {
        return _.flatten(_.map(collection, iteratee));
    }
});

Examples:

例子:

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 => o.a).filter(a => a % 2 === 0).map(a => a * 3).value()); // [ 6, 12 ]

回答by mpen

I couldn't find any methods in lodash that work quite like SelectMany, so I created one using pure JS:

我在 lodash 中找不到任何与 类似的方法SelectMany,所以我使用纯 JS 创建了一个:

Array.prototype.selectMany = function(fn) {
    return Array.prototype.concat(...this.map(fn));
};

Boom.

繁荣。

> console.log([{a:[1,2],b:'x'},{a:[3,4],b:'y'}].selectMany(o => o.a));
[ 1, 2, 3, 4 ]