How to Filter an Array by a Condition

javascript filter array multiple conditions

You can do like this

var filter = {  address: 'England',  name: 'Mark'};var users = [{    name: 'John',    email: 'johnson@mail.com',    age: 25,    address: 'USA'  },  {    name: 'Tom',    email: 'tom@mail.com',    age: 35,    address: 'England'  },  {    name: 'Mark',    email: 'mark@mail.com',    age: 28,    address: 'England'  }];

users= users.filter(function(item) { for (var key in filter) { if (item[key] === undefined || item[key] != filter[key]) return false; } return true;});
console.log(users)

Filter array of object with conditional statement

This is very simple to do by using Array.protoype.filter. Within the filter callback, you can use String.protoype.includes method to check if the title includes "grapes":

const fruits = [{
"id": "1",
"title": "Banana",
"description": "1 Minute"
},
{
"id": "2",
"title": "Apple",
"description": "2 - 3 Days"
},
{
"id": "3",
"title": "Manggo",
"description": "10 - 20 Days"
},
{
"id": "4",
"title": "Orange",
"description": "10 - 20 Days"
},
{
"id": "5",
"title": "Grape blue",
"description": "10 - 20 Days"
},
{
"id": "6",
"title": "Grape red",
"description": "10 - 20 Days"
}
];

const filteredFruits = fruits.filter(fruit => {
if (!fruit.title.toLowerCase().includes("grape")) {
if (fruit.description === "10 - 20 Days") {
return true;
}
}

return false;
});

console.dir(filteredFruits)

How to filter an array based on condition

You can use filter to find the array of permissions from a certain user:

roleInfo
.filter(roles=>roles[0].model==="schedule")[0]

Use reduce to create your object and switch for each property.

rolesForUser
.reduce(
(info,item)=>{
switch(item.property) {
case 'find':
info.canFetchData = (item.permission==='allow')?true:false
break;
//other cases
}
return info;
},
{menu_name : user}//initial info object with menu_name set to user
);

const roleInfo = [  [    { model: 'user', property: 'find', permission: 'allow' },    { model: 'user', property: 'create', permission: 'allow' },    { model: 'user', property: 'update', permission: 'deny' },    { model: 'user', property: 'delete', permission: 'deny' }  ],  [    { model: 'registration', property: 'find', permission: 'allow' },    { model: 'registration', property: 'create', permission: 'deny' },    { model: 'registration', property: 'update', permission: 'deny' },    { model: 'registration', property: 'delete', permission: 'deny' }  ],  [    { model: 'schedule', property: 'find', permission: 'allow' },    { model: 'schedule', property: 'create', permission: 'allow' },    { model: 'schedule', property: 'update', permission: 'allow' },    { model: 'schedule', property: 'delete', permission: 'deny' }  ]];
const getRoleForUser = (user,roleInfo) => roleInfo .filter(roles=>roles[0].model===user)[0] .reduce( (info,item)=>{ switch (item.property) { case 'find': info.canFetchData = (item.permission==='allow')?true:false break; case 'create': info.canCreateData = (item.permission==='allow')?true:false break; case 'update': info.canUpdateData = (item.permission==='allow')?true:false break; case 'delete': info.canDeleteData = (item.permission==='allow')?true:false break; default: throw new Error(`${item.property} is an unknown permission`); } return info; }, {menu_name : user} );
console.log(getRoleForUser("registration",roleInfo));

How to filter an array by a condition

$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);


function filterArray($value){
return ($value == 2);
}

$filteredArray = array_filter($fullArray, 'filterArray');

foreach($filteredArray as $k => $v){
echo "$k = $v";
}

Is there a way to filter an array of objects with multiple dynamic conditions

You are essentially implementing a domain specific language where you need to convert language expressions into runnable programs. For this particular language, we wish to convert expressions from plain JavaScript objects into a JavaScript function -

function evaluate(expr) {
switch (expr?.type) {
case "filter":
return v => evaluateFilter(v, expr)
case "and":
return v => expr.filters.every(e => evaluate(e)(v))
case "or":
return v => expr.filters.some(e => evaluate(e)(v))
//case ...:
// implement any other filters you wish to support
default:
throw Error(`unsupported filter expression: ${JSON.stringify(expr)}`)
}
}

Then we take the resulting function and plug it directly into Array.prototype.filter. The basic usage will look like this -

myinput.filter(evaluate({ /* your domain-specific expression here */ })

Next, evaluateFilter is the low-level function that you have already written. Here it is implemented as a single function, but you could separate it more if you desire -

function evaluateFilter(t, {key, condition, value}) {
switch (condition) {
case "is":
return t?.[key] == value
case "is greater than":
return t?.[key] > value
case "is less than":
return t?.[key] < value
case "is not":
return t?.[key] != value
//case ...:
// implement other supported conditions here
default:
throw Error(`unsupported filter condition: ${condition}`)
}
}

Given some input such as -

const input = [
{ type: "fruit", name: "apple", count: 3 },
{ type: "veggie", name: "carrot", count: 5 },
{ type: "fruit", name: "pear", count: 2 },
{ type: "fruit", name: "orange", count: 7 },
{ type: "veggie", name: "potato", count: 3 },
{ type: "veggie", name: "artichoke", count: 8 }
]

We can now write simple expressions with a single filter -

input.filter(evaluate({
type: "filter",
condition: "is",
key: "type", value: "fruit"
}))
[
{
"type": "fruit",
"name": "apple",
"count": 3
},
{
"type": "fruit",
"name": "pear",
"count": 2
},
{
"type": "fruit",
"name": "orange",
"count": 7
}
]

Or rich expressions that combine multiple filters using and and/or or -

input.filter(evaluate({
type: "and",
filters: [
{
type: "filter",
condition: "is not",
key: "type",
value: "fruit"
},
{
type: "filter",
condition: "is greater than",
key: "count",
value: "3"
}
]
}))
[
{
"type": "veggie",
"name": "carrot",
"count": 5
},
{
"type": "veggie",
"name": "artichoke",
"count": 8
}
]

The evaluator is recursive so you can combine and and/or or in any imaginable way -

input.filter(evaluate({
type: "or",
filters: [
{
type: "filter",
condition: "is less than",
key: "count",
value: 3
},
{
type: "and",
filters: [
{
type: "filter",
condition: "is not",
key: "type",
value: "fruit"
},
{
type: "filter",
condition: "is greater than",
key: "count",
value: "3"
}
]
}
]
}))
[
{
"type": "veggie",
"name": "carrot",
"count": 5
},
{
"type": "fruit",
"name": "pear",
"count": 2
},
{
"type": "veggie",
"name": "artichoke",
"count": 8
}
]

Expand the snippet to verify the result in your own browser -

function evaluate(expr) {
switch (expr?.type) {
case "filter":
return v => evaluateFilter(v, expr)
case "and":
return v => expr.filters.every(e => evaluate(e)(v))
case "or":
return v => expr.filters.some(e => evaluate(e)(v))
default:
throw Error(`unsupported filter expression: ${JSON.stringify(expr)}`)
}
}

function evaluateFilter(t, {key, condition, value}) {
switch (condition) {
case "is":
return t?.[key] == value
case "is greater than":
return t?.[key] > value
case "is less than":
return t?.[key] < value
case "is not":
return t?.[key] != value
default:
throw Error(`unsupported filter condition: ${condition}`)
}
}

const input = [
{ type: "fruit", name: "apple", count: 3 },
{ type: "veggie", name: "carrot", count: 5 },
{ type: "fruit", name: "pear", count: 2 },
{ type: "fruit", name: "orange", count: 7 },
{ type: "veggie", name: "potato", count: 3 },
{ type: "veggie", name: "artichoke", count: 8 }
]

console.log(input.filter(evaluate({
type: "filter",
condition: "is",
key: "type", value: "fruit"
})))

console.log(input.filter(evaluate({
type: "and",
filters: [
{
type: "filter",
condition: "is not",
key: "type",
value: "fruit"
},
{
type: "filter",
condition: "is greater than",
key: "count",
value: "3"
}
]
})))

console.log(input.filter(evaluate({
type: "or",
filters: [
{
type: "filter",
condition: "is less than",
key: "count",
value: 3
},
{
type: "and",
filters: [
{
type: "filter",
condition: "is not",
key: "type",
value: "fruit"
},
{
type: "filter",
condition: "is greater than",
key: "count",
value: "3"
}
]
}
]
})))

Filter array of object based on multiple conditions in React

The issue is that you are applying all of your filters instead of just ones that are defined. And also you also should just return false from your filters if they are defined, that is the only way to run through all of them. So your code should look something like this

const filteredAllPersons = oldPersons.filter(person => {
if (genderFilter && person.gender !== genderFilter) {
return false
}
// apply all other filters the same as above

// Finally return true because record has satisfied all conditions
return true
})

How to filter array of objects on multiple conditions and add exception?

I kept the filtering part you implemented as an intermediate output. using that i got a count for each id. then using that i filtered out from the intermediate array where if the has count > 1 and has a null name i remove it.

 const data = [{id: 1234,name: "Name1"},{id: 1234,name: "Name1"},{id: 1234,name: "Name2"},{id: 1234,name: null},{id: 5678,name: "Name3"},{
id: 5678,name: "Name3"},{id: 5678,name: null},{id: 9999,name: null},{id: 9999,name: null},];

//filtering out duplicates
let a = data.filter((value, index, self) => {
return (
self.findIndex(
(v) =>
v.id === value.id &&
v.name=== value.name
) === index
);
});

//get count for ids in partially filtered
let idcount = a.reduce((acc,curr) => {
if(!acc[curr.id])acc[curr.id] = 0
acc[curr.id] += 1
return acc;
},{})

//remove the duplicate nulls
let final = a.filter((el) => {
return !(idcount[el.id]>1 && el.name===null)
})


console.log(final)

JavaScript multiple condition filtering with array of conditions?

You can use a higher order filter function to handle applying filter conditions and is passed to your array.prototype.filter function.

const filterData = ({ filters = [], every = false }) => (el) =>
filters[every ? "every" : "some"]((filterFn) => filterFn(el));

This consumes an options object that defines an array of filter condition functions that accept a single element value/object from your data array and returns the function used for the array filtering.

Example:

// AC AND nonAC
data.filter(filterData({
filters: [
({ AC, nonAC }) => AC && nonAC,
],
}))

Edit javascript-multiple-condition-filtering-with-array-of-conditions

Note

If your data is in the form

"AC": "false"

Where the booleans are stringified then make the following adjustment to your condition checkers, compare to === 'true':

({ AC, nonAC }) => AC === "true" || nonAC === "true"

Edit

After discussion it seems some of these conditions are not mutually inclusive, or rather, they are only mutually inclusive in specific groups.

Still using a Higher Order Function, the logic is tweaked a bit to consume the array of key-value conditions.

Create a mapping function to map your user selected filters ([{ AC: "true" }, ...]) to a groups of "filterBy" values that are mutually inclusive. These will be logical OR'd (||) together while the sets will be exclusive by using logical AND'd (&&) together.

const mapfiltersToSets = (filters) => {
const filtersObject = filters.reduce((conditions, condition) => {
const [key, value] = Object.entries(condition).pop();

switch (key) {
case "AC":
case "nonAC":
return {
...conditions,
acConditions: [...(conditions.acConditions || []), { key, value }]
};

case "seater":
case "sleeper":
return {
...conditions,
seatSleeper: [...(conditions.seatSleeper || []), { key, value }]
};

// add new AND groups here

default:
return conditions;
}
}, {});
return Object.values(filtersObject);
};

const filterData = (filters = []) => (el) =>
mapfiltersToSets(filters).every((filterSet) =>
filterSet.some(({ key, value }) => el[key] === value)
);

Example:

// AC AND nonAC
data.filter(filterData([{ AC: "true" }, { nonAC: "true" }]))

Demo with extended dataset and unit tests. Good start to build from.

Edit javascript-multiple-condition-filtering-with-array-of-conditions (forked)

Javascript multiple condition array filter

// You wrote that it's an array, so changed the braces 
var filtercondition = ["p",
{acct1:true,acct2:false,acct3:true...}
"2016-06-01",
"2016-11-30",
"category3"
];

var filtered = data.filter(o => {
if(filtercondition[0] && !o.category.includes(filtercondition[o])) { // checking just the category, but you can check if any of more fields contains the conditions
return false;
}
if(filtercondition[1]) {
for(var key in filtercondition[1]) {
if(filtercondition[1][key] === true && o.acct != key) {
return false;
}
}
}
if(filtercondition[2] && o.transdate < filtercondition[2]) {
return false;
}
if(filtercondition[3] && o.transdate > filtercondition[3]) {
return false;
}
if(filtercondition[4] && o.category !== filtercondition[4]) {
return false;
}

return true;
});

Two notes:
- changed the braces of filtercondition so that it is an array, however I would suggest to use an object instead.
- this {acct1:true,acct2:false,acct3:true...} sample doesn't make sense for me, since it suggests that the acct field should be acct1 and acct3 at the same time.



Related Topics



Leave a reply



Submit