简体   繁体   中英

filter array of object on multi conditions

I have this array

const d = [{
    "type": "price",
    "value": {
        "min": 0,
        "max": 170
    }
}, {
    "type": "name",
    "value": {}
}, {
    "type": "volume",
    "options": [1,2]
}]

I want to filter if value doesn't have a value or options is an empty array. So I did

d.filter(o => o.value || o.options)

I expect type:name is gone but why it's still there?

I also tried lodash

d.filter(o => !isEmpty(o.value) || !isEmpty(o.options))

doesn't work as expected?

{} and [] are truthy values

 console.log(Boolean([])) console.log(Boolean({})) 

You can check for length in case of array, in case of object you can get keys or values or entries and check it's length

 const d = [{"type": "price","value": {"min": 0,"max": 170}}, {"type": "name","value": {}}, {"type": "volume","options": [1,2]}] let op = d.filter(o => ( Object.values(o.value || {}) || (o.options || [] )).length) console.log(op) 

{} is still a truthy value, you must check for its keys' length

 const d = [{ "type": "price", "value": { "min": 0, "max": 170 } }, { "type": "name", "value": {} }, { "type": "volume", "options": [1,2] }] console.log(d.filter(o => (o.value && Object.keys(o.value).length) || o.options)) 

Here is my solution.

 const d = [{ "type": "price", "value": { "min": 0, "max": 170 } }, { "type": "name", "value": {} }, { "type": "volume", "options": [1,2] }] function notEmpty(n){ return (!!n ? typeof n === 'object' ? Array.isArray(n) ? !!n.length : !!Object.keys(n).length : true : false); } console.log(d.filter(o => notEmpty(o.value) || notEmpty(o.options))); 

Hope will help you.

Give the custom filter callback where you check for any entry in values property and options property.

 const d = [ { "type": "price", "value": { "min": 0, "max": 170 } }, { "type": "name", "value": {} }, { "type": "volume", "options": [1,2] } ]; function doesHaveValuesAndOptions(obj) { const valueEntries = obj.value ? Object.entries(obj.value) : [], options = obj.options || []; if (!valueEntries.length && !options.length) return false; else if (valueEntries.length || options.length) return true; return false; } const res = d.filter(doesHaveValuesAndOptions); console.log(res); 

With lodash, you can use _.reject() with _.isEmpty() to remove items that have an empty value object and an empty options array:

 const arr = [{"type": "price","value": {"min": 0,"max": 170}}, {"type": "name","value": {}}, {"type": "volume","options": [1,2]}] const result = _.reject(arr, o => _.isEmpty(o.value) && _.isEmpty(o.options)) console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script> 

With lodash/fp you can easily generate a function that extracts the value and the options , iterates them with _.every() and return true (should be removed) if both are empty:

 const { reject, flow, props, every, isEmpty } = _ const fn = reject(flow(props(['value', 'options']), every(isEmpty))) const arr = [{"type": "price","value": {"min": 0,"max": 170}}, {"type": "name","value": {}}, {"type": "volume","options": [1,2]}] const result = fn(arr) console.log(result) 
 <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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