最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I find if one or more array elements match in lodash find - Stack Overflow

programmeradmin0浏览0评论

Using lodash _.find(), we can see if there's a matching object in a collection.

var users = [
  { 'user': 'barney',  'age': 36, 'active': true,  arr: [2, 3, 6, 9] },
  { 'user': 'fred',    'age': 40, 'active': false, arr: [2, 3, 6, 9] },
  { 'user': 'pebbles', 'age': 1,  'active': true,  arr: [2, 3, 6, 9] }
];

You can provide an array, and an object matches if all values in that array are present in the collection. Notice the arr.

_.result(_.find(users, { 'age': 1, 'active': true, 'arr': [2, 9] }), 'user');
// Result: "pebbles"

How can I match objects that have one (or more) matching array items for any array in the match object? (In this case arr.) Something similar to the $in query from MongoDB.

_.result(_.find(users, { 'age': 1, 'active': true, 'arr': [2, 4] }), 'user');
// Result: undefined
// Expected: "pebbles"

Using lodash _.find(), we can see if there's a matching object in a collection.

var users = [
  { 'user': 'barney',  'age': 36, 'active': true,  arr: [2, 3, 6, 9] },
  { 'user': 'fred',    'age': 40, 'active': false, arr: [2, 3, 6, 9] },
  { 'user': 'pebbles', 'age': 1,  'active': true,  arr: [2, 3, 6, 9] }
];

You can provide an array, and an object matches if all values in that array are present in the collection. Notice the arr.

_.result(_.find(users, { 'age': 1, 'active': true, 'arr': [2, 9] }), 'user');
// Result: "pebbles"

How can I match objects that have one (or more) matching array items for any array in the match object? (In this case arr.) Something similar to the $in query from MongoDB.

_.result(_.find(users, { 'age': 1, 'active': true, 'arr': [2, 4] }), 'user');
// Result: undefined
// Expected: "pebbles"
Share Improve this question edited Oct 15, 2015 at 20:04 Redsandro asked Oct 15, 2015 at 19:02 RedsandroRedsandro 11.4k15 gold badges80 silver badges111 bronze badges 1
  • 1 find multiple times and add them to a set? – ergonaut Commented Oct 15, 2015 at 19:08
Add a ment  | 

2 Answers 2

Reset to default 2

From the fine manual:

If an object is provided for predicate the created _.matches style callback returns true for elements that have the properties of the given object, else false.

and _.matches does element-by-element equality tests with arrays so you can't use an object predicate for what you want to do. However, you don't have to pass an object to _.find, you can pass a function:

Iterates over elements of collection, returning the first element predicate returns truthy for. The predicate is bound to thisArg and invoked with three arguments: (value, index|key, collection).

The object form of _.find that you're using just builds a predicate function behind the curtains. You can always supply your own predicate function if you need to:

_.find(users, function(value) {
    if(value.age !== 1)
        return false;
    if(!value.active)
        return false;
    if(_.intersection(value.arr, [2, 4]).length <= 0)
        return false;
    return true;
})

Of course, if your arrays aren't really sets (i.e. there could be duplicates or order matters) then you'd have to replace with _.intersection test with something that matches your specific requirements.

Demo: http://jsfiddle/ambiguous/vo72Lyce/

If you want this to work for arbitrary objects then you'd write your own version of _.matches (probably by starting with the current implementation) that does what you want; then you could use your version of _.matches to build the predicate function for _.find.

As far as I know, you cannot do that in lodash.

What fuzzyMatcher does is create an array of functions where each function corresponds to a single property in the object you are trying to match on. Those functions will return true if that property matches the property in the user object. Then fuzzyMatcher runs each of those functions and gets the count of the functions which returned true. Then it returns true if the number of matching functions is greater than or equal the number of desired matches (1 in your case).

This seems to work pretty well:

function fuzzyMatcher(collection, matchObj, minSimilarProps) {
    var matchFns = [];

    _.forOwn(matchObj, function(value, key) {
        matchFns.push(_.matchesProperty(key, value));
    });

    return _.find(collection, function(u) {
        return _.filter(matchFns, function(fn) {
            return fn(u);
        }).length >= minSimilarProps;
    });
}

//matches 1 properties
fuzzyMatcher(users, { 'age': 1, 'active': true, 'arr': [2, 4] }, 1);

//or matches 2 properties
fuzzyMatcher(users, { 'age': 1, 'active': true, 'arr': [2, 4] }, 2);

Or in your case:

_.result(fuzzyMatcher(users, { 'age': 1, 'active': true, 'arr': [2, 4] }, 2), 'user');

Also I think you need to reword what you want to say "two or more" since once or more would match barney since active=1 in both cases.

发布评论

评论列表(0)

  1. 暂无评论