lodash使用值数组过滤集合

Ami*_*ava 53 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
});
Run Code Online (Sandbox Code Playgroud)

jes*_*vin 62

如果你要经常使用这种模式,你可以像下面那样创建一个mixin,但它没有做与原始代码不同的任何有趣的事情.它只是让开发人员更友好.

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

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

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]);
Run Code Online (Sandbox Code Playgroud)

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

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


Ada*_*uch 39

一个简洁的lodash解决方案,它使用indexBy()at().

_(collections)
    .indexBy('id')
    .at(ids)
    .value();
Run Code Online (Sandbox Code Playgroud)

  • 这种解决方案的简洁性非常出色.并且Lodash 4用户可以简单地用`keyBy`替换`indexBy`以继续运行. (8认同)
  • 如果`collections`不包含任何与`ids`匹配的对象,它似乎返回一个带有一个未定义元素的数组.`[undefined`].这对我的'someArray.length`测试失败了,所以我添加了一个`.filter()``_(collections).keyBy('id').at(ids).filter().value();` (2认同)

Jee*_*van 17

我们也可以像这样过滤

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);
Run Code Online (Sandbox Code Playgroud)


ede*_*bin 9

这对我很有用:

let output = _.filter(collections, (v) => _.includes(ids, v.id));
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这对我也有用,但是,我使用 `reject` 来简化过滤器 `let output = _.reject(collections, v => _.includes(ids, v.id)); ` (2认同)

Ben*_*ema 7

我喜欢jessegavin的答案,但我使用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
Run Code Online (Sandbox Code Playgroud)

的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);
}
Run Code Online (Sandbox Code Playgroud)

如果您不信任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;
}
Run Code Online (Sandbox Code Playgroud)

  • lodash`get`默认是深的,所以你可以做`_.get(object,'a [0] .b.c');`.所以你需要做的就是让@jessegavin回答支持深度属性是用`_.get(item,property)`改变`item [property]`.参见[lodash documents](https://lodash.com/docs#get). (3认同)