Подтвердить что ты не робот

Что такое underscore.js, эквивалентное оператору LINQ SelectMany?

Представьте, что у меня есть структура вложенных массивов.

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

Используя underscore.js, как бы я создавал сплющенный массив?

В С# вы должны использовать Enumerable.SelectMany следующим образом:

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

Обратите внимание, что лямбда в этом случае выбирает вложенный элемент напрямую, но это могло быть любое произвольное выражение.

В jQuery можно просто использовать:

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

Однако этот подход не работает с функцией подчеркивания map.

Итак, как бы получить сплющенный массив [1, 2, 3] с помощью underscore.js?

4b9b3361

Ответ 1

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

Heres a fiddle

Ответ 2

Если у вас несколько более сложный массив, скажем, один из JSON, вы можете использовать метод pluck, извлекая конкретное свойство, которое вас интересует, аналогично parents.SelectMany(parent => parent.Items);

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

allitems теперь является массивом всех подэлементов от родителей, [a,b,c,d].

И JSFiddle, показывающий то же самое.


Или, если вы используете 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) {
    document.getElementById('result').innerHTML += wat + ':' + JSON.stringify(value) + '\r\n<br/>';
}
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script>
<div id="result"></div>

Ответ 3

Мы также можем сделать решение Патрика в 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 => o.a).filter(a => a % 2 === 0).map(a => a * 3).value()); // [ 6, 12 ]

Ответ 4

Я не мог найти какие-либо методы в 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 ]