简体   繁体   English

使用模糊匹配在集合中查找对象

[英]Find object in collection with fuzzy matching

I have a collection that looks something like this: 我有一个看起来像这样的集合:

const collection = [
    {
        name: 'THIS_ITEM',
        conditions: {
            oneCondition: false,
            anotherCondition: false,
            yourCondition: false,
            myCondition: false
        }
    }, {
        name: 'THAT_ITEM',
        conditions: {
            oneCondition: false,
            anotherCondition: false,
            yourCondition: true,
            myCondition: false
        }
    }, {
        name: 'THOSE_ITEMS',
        conditions: {
            oneCondition: true,
            anotherCondition: false,
            yourCondition: null,
            myCondition: false
        }
    }
];

… and later an object that looks like this: ......以及后来看起来像这样的对象:

const condition = {
    oneCondition: true,
    anotherCondition: false,
    yourCondition: true,
    myCondition: false
};

I'm trying to match the condition object against the nested conditions objects in collection to find the one that matches so I can retrieve the name property from the matching entry. 我正在尝试将condition对象与collection中的嵌套conditions对象进行匹配,以找到匹配的对象,这样我就可以从匹配的条目中检索name属性。

The thing that's throwing me for a loop is the fact that the conditions properties can have “fuzzy” values. 抛弃循环的事情是conditions属性可以具有“模糊”值。 By that I mean that if any properties in the source collection are set to true or false they MUST match the values in condition exactly. 我的意思是,如果源collection中的任何属性设置为truefalse它们必须完全匹配condition中的值。 But if the property in the source collection has a value of null it can match either true or false . 但是,如果源在属性collection的值为null它可以匹配 truefalse

Example: 例:

These would match: 这些将匹配:

const condition = {
    oneCondition: true,
    anotherCondition: false,
    yourCondition: true,
    myCondition: false
};

const collection = [
    …
    }, {
        name: 'THOSE_ITEMS',
        conditions: {
            oneCondition: true,
            anotherCondition: false,
            yourCondition: null,
            myCondition: false
        }
    }
];

These would not: 这些不会:

const condition = {
    oneCondition: true,
    anotherCondition: false,
    yourCondition: true,
    myCondition: false
};

const collection = [
    …
    }, {
        name: 'THAT_ITEM',
        conditions: {
            oneCondition: false,
            anotherCondition: false,
            yourCondition: true,
            myCondition: false
        }
    }, {
    …
];

Any suggestions? 有什么建议? I'm using Lodash but can't seem to imagine any solution without an overly-verbose and nested concoction. 我正在使用Lodash,但似乎无法想象没有过于冗长和嵌套的混合物的任何解决方案。

You could use Array#filter with Array#every for the conditions and test against null value as wildcard. 您可以将Array#filterArray#every用于条件,并将null值作为通配符进行测试。

 var collection = [{ name: 'THIS_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: false, myCondition: false } }, { name: 'THAT_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: true, myCondition: false } }, { name: 'THOSE_ITEMS', conditions: { oneCondition: true, anotherCondition: false, yourCondition: null, myCondition: false } }], condition = { oneCondition: true, anotherCondition: false, yourCondition: true, myCondition: false }, result = collection.filter(o => Object.keys(condition).every(k => o.conditions[k] === null || o.conditions[k] === condition[k] ) ); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

You can use lodash#filter with lodash#isMatch and lodash#omitBy to match the condition against a collection object's condition that doesn't contain any null values. 您可以将lodash#filterlodash#isMatchlodash#omitBy以将condition与不包含任何null值的集合对象的条件进行匹配。

const result = _.filter(collection, v => 
  _.isMatch(condition, _.omitBy(v.conditions, _.isNull))
);

 const collection = [ { name: 'THIS_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: false, myCondition: false } }, { name: 'THAT_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: true, myCondition: false } }, { name: 'THOSE_ITEMS', conditions: { oneCondition: true, anotherCondition: false, yourCondition: null, myCondition: false } } ]; const condition = { oneCondition: true, anotherCondition: false, yourCondition: true, myCondition: false }; const result = _.filter(collection, v => _.isMatch(condition, _.omitBy(v.conditions, _.isNull)) ); console.log(result); 
 body > div { min-height: 100%; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> 

You can filter the collecting using lodash's _.isMatchWith() : 您可以使用lodash的_.isMatchWith()过滤收集:

 const condition = {"oneCondition":true,"anotherCondition":false,"yourCondition":true,"myCondition":false}; const collection = [{"name":"1","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":true,"myCondition":false}},{"name":"2","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":false,"myCondition":false}},{"name":"3","conditions":{"oneCondition":true,"anotherCondition":false,"yourCondition":null,"myCondition":false}}]; const result = collection.filter(({ conditions }) => _.isMatchWith(condition, conditions, (objValue, othValue) => objValue === null || othValue === null || objValue === othValue) // if at least one of the values is null or they are equal ); console.log(result); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script> 

You can use a combination of lodash .filter() , 你可以使用lodash .filter()的组合 .every() and .isEqual() methods to loop over the collection and filter only items which have the same conditions as your object: .every().isEqual()方法循环遍历collection并仅过滤与对象具有相同条件的项:

_.filter(collection, function(c) {
  return _.every(_.keys(condition), function(currentKey) {
    return c.conditions[currentKey] === null ||
      _.isEqual(c.conditions[currentKey], condition[currentKey]);
  });
});

Demo: 演示:

 const collection = [{ name: 'THIS_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: false, myCondition: false } }, { name: 'THAT_ITEM', conditions: { oneCondition: false, anotherCondition: false, yourCondition: true, myCondition: false } }, { name: 'THOSE_ITEMS', conditions: { oneCondition: true, anotherCondition: false, yourCondition: null, myCondition: false } }]; const condition = { oneCondition: true, anotherCondition: false, yourCondition: true, myCondition: false }; var result = _.filter(collection, function(c) { return _.every(_.keys(condition), function(currentKey) { return c.conditions[currentKey] === null || _.isEqual(c.conditions[currentKey], condition[currentKey]); }); }); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="http://underscorejs.org/underscore-min.js"></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM