web-dev-qa-db-fra.com

Quel est le soussecore.js équivalent à l'opérateur SelectMany de Linq?

Imaginez que j'ai une structure de matrice imbriquée.

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

Utilisation nderscore.js , comment ferais-je produire un tableau aplatie?

En C #, vous utiliseriez Enumerable.SelectMany comme ceci:

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

Notez que la Lambda dans ce cas sélectionne directement l'élément imbriqué, mais cela aurait pu être une expression arbitraire.

À JQuery, il est possible de simplement utiliser:

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

Cependant, cette approche ne fonctionne pas avec la fonction de sous-traitance carte .

Alors, comment puis-je obtenir le tableau aplatie [1, 2, 3] utiliser des sous-traitants.js?

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

Heres A violon

40
armen.shimoon

Si vous avez une matrice légèrement plus compliquée, dites-en une venant de JSON, vous pouvez également profiter de la méthode PLUCK Méthode, extrayant la propriété spécifique qui vous intéresse, similaire à parents.SelectMany(parent => parent.Items);

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

allitems est maintenant le tableau de tous les subitems des parents, [a,b,c,d].

Et a jsfiddle montrant la même chose.


Ou, si vous utilisez Lodash, vous pouvez faire la même chose en utilisant la fonction _. Platmap Fonction disponible depuis la version 4. Crédiez à Noel pour le pointer dans les commentaires.

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>

Si vous souhaitez faire plus de choses et que vous ne voulez pas de chaîner des opérateurs, vous pouvez utiliser la fonction flow fonction pour obtenir le même effet. Ceci est utile si vous utilisez des documents dotés et importaient chaque opérateur individuellement, car vous pouvez ensuite optimiser votre charge utile finale.

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>
41
Patrick

Nous pouvons également faire Solution de Patrick dans un mixin de sorte qu'il devienne charabitable:

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

Exemples:

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 ]
3
mpen

Je ne pouvais trouver aucune méthode dans Lodash qui fonctionne tout à fait comme SelectMany, donc j'ai créé un en utilisant Pure 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 ]
2
mpen