web-dev-qa-db-fra.com

collection de filtres utilisant un tableau de valeurs

Je voudrais filtrer une collection en utilisant un tableau de valeur de propriété. Avec un tableau d'identifiants, retourne les objets avec les identifiants correspondants. Existe-t-il une méthode de raccourci utilisant lodash/underscore?

var collections = [{ id: 1, name: 'xyz' },
                   { id: 2,  name: 'ds' },
                   { id: 3,  name: 'rtrt' },
                   { id: 4,  name: 'nhf' },
                   { id: 5,  name: 'qwe' }];
var ids = [1,3,4];

// This works, but any better way?

var filtered = _.select(collections, function(c){    
    return ids.indexOf(c.id) != -1
});
50
SamSerious

Si vous utilisez beaucoup ce type de motif, vous pouvez créer un mixin similaire au suivant, cependant, il ne fait rien de fondamentalement différent de votre code d'origine. Cela le rend plus convivial pour les développeurs.

_.mixin({
  'findByValues': function(collection, property, values) {
    return _.filter(collection, function(item) {
      return _.contains(values, item[property]);
    });
  }
});

Ensuite, vous pouvez l'utiliser comme ça.

var collections = [
    {id: 1, name: 'xyz'}, 
    {id: 2,  name: 'ds'},
    {id: 3,  name: 'rtrt'},
    {id: 4,  name: 'nhf'},
    {id: 5,  name: 'qwe'}
];

var filtered = _.findByValues(collections, "id", [1,3,4]);

Update - La réponse ci-dessus est ancienne et maladroite. Veuillez utiliser le réponse de Adam Boduch pour une solution beaucoup plus élégante.

_(collections)
  .keyBy('id') // or .indexBy() if using lodash 3.x
  .at(ids)
  .value();
59
jessegavin

Une solution concise de lodash utilisant indexBy () et at () .

_(collections)
    .indexBy('id')
    .at(ids)
    .value();
35
Adam Boduch

On peut aussi filtrer comme ça

var collections = [{ id: 1, name: 'xyz' },
            { id: 2,  name: 'ds' },
            { id: 3,  name: 'rtrt' },
            { id: 4,  name: 'nhf' },
            { id: 5,  name: 'qwe' }];



        var filtered_ids = _.filter(collections, function(p){
            return _.includes([1,3,4], p.id);
        });

        console.log(filtered_ids);
15
Jeevan

J'aime jessegavin answer, mais je l'ai développé en utilisant lodash-deep pour la correspondance des propriétés en profondeur.

var posts = [{ term: { name: 'A', process: '123A' } }, 
             { term: { name: 'B', process: '123B' } }, 
             { term: { name: 'C', process: '123C' } }];

var result = _.filterByValues(posts, 'term.process', ['123A', '123C']);
// results in objects A and C to be returned

jsFiddle

_.mixin({
    'filterByValues': function(collection, key, values) {
        return _.filter(collection, function(o) {
            return _.contains(values, resolveKey(o, key));
        });
    }
});

function resolveKey(obj, key) {
    return (typeof key == 'function') ? key(obj) : _.deepGet(obj, key);
}

Si vous ne faites pas confiance à lodash-deep ou si vous souhaitez que les propriétés dont le nom est composé de points soient prises en charge, voici une version plus défensive et robuste:

function resolveKey(obj, key) {
    if (obj == null || key == null) {
        return undefined;
    }
    var resolved = undefined;
    if (typeof key == 'function') {
        resolved = key(obj);
    } else if (typeof key == 'string' ) {
        resolved = obj[key];
        if (resolved == null && key.indexOf(".") != -1) {
            resolved = _.deepGet(obj, key);
        }
    }
    return resolved;
}
6
Benny Bottema

Ces réponses n'ont pas fonctionné pour moi, car je voulais filtrer sur une valeur non unique. Si vous remplacez keyBy par groupBy, vous pourrez vous débrouiller.

_(collections)
  .groupBy(attribute)
  .pick(possibleValues)
  .values()
  .flatten()
  .value();

Mon utilisation initiale étant de laisser tomber des objets, j'ai donc remplacé pick par omit.

Merci Adam Boduch pour le point de départ.

1
migpok35

J'ai remarqué que beaucoup de ces réponses sont obsolètes ou contiennent des fonctions auxiliaires non répertoriées dans la documentation Lodash. La réponse acceptée inclut la fonction obsolète _.contains et doit être mise à jour.

Alors voici ma réponse ES6.

Basé sur Lodash v4.17.4

_.mixin( {
    filterByValues: ( c, k, v ) => _.filter(
        c, o => _.indexOf( v, o[ k ] ) !== -1
    )
} );

Et invoqué comme tel:

_.filterByValues(
    [
        {
            name: 'StackOverflow'
        },
        {
            name: 'ServerFault'
        },
        {
            name: 'AskDifferent'
        }
    ],
    'name',
    [ 'StackOverflow', 'ServerFault' ]
);

// => [ { name: 'StackOverflow' }, { name: 'ServerFault' } ]
1
iSkore

Cela a bien fonctionné pour moi:

let output = _.filter(collections, (v) => _.includes(ids, v.id));
1
edencorbin