lodash使用值数组过滤集合

时间:2013-06-22 14:23:57

标签: underscore.js lodash

我想使用属性值数组过滤集合。给定一组ID,返回具有匹配ID的对象。是否有使用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
});

6 个答案:

答案 0 :(得分:59)

如果你要使用这种模式,你可以创建一个如下所示的mixin,但它没有做与原始代码完全不同的任何事情。它只是让它更适合开发人员。

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

然后你可以像这样使用它。

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]);

更新 - 以上答案陈旧且笨重。请使用answer from Adam Boduch获得更优雅的解决方案。

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

答案 1 :(得分:16)

我们也可以像这样过滤

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);

答案 2 :(得分:6)

我喜欢jessegavin's回答,但我使用lodash-deep对其进行了深入的属性匹配。

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);
}

如果您不信任lodash-deep,或者您希望支持名称中包含点的属性,那么这是一个更具防御性且更强大的版本:

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;
}

答案 3 :(得分:1)

我注意到其中许多答案已过时或包含Lodash文档中未列出的辅助功能。接受的答案包括已弃用的函数_.contains,应予以更新。

所以这是我的ES6答案。

基于Lodash v4.17.4

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

并且这样调用:

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

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

答案 4 :(得分:1)

这些答案对我不起作用,因为我想过滤一个非唯一的值。如果您将groupBy更改为_(collections) .groupBy(attribute) .pick(possibleValues) .values() .flatten() .value(); ,则可以通过。

pick

我最初使用的是丢弃内容,因此我使用omit切换了{{1}}。

感谢Adam Boduch作为起点。

答案 5 :(得分:1)

这对我很有用:

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