Reputation: 23
Value of typeOfFilters is selected from different component, so in my current component I get value of currency and frequency, but my filter function doesn't iterate over frequency.
I want to add more filters to my filter function. Do tell me how can i simplify this problem? plans looks like this.
let plans = [
{
"amount": 6000,
"currency": "USD",
"frequency": "MONTH",
"planId": "plan_L7mrzVML9o6G5c",
"planName": "computer",
"provider": "stripe"
},
{
"amount": 2000,
"currency": "INR",
"frequency": "DAY",
"planId": "plan_KkHkJPEVR7ZA2s",
"planName": "Platinum",
"provider": "stripe"
}
]
const typeOfFilters = {
currency: ['INR'],
frequency: ['DAY'],
provider: "",
amount: "",
status: "",
}
const sortedTableArray = plans.filter(function (plan) {
for (const [f, values] of Object.entries(typeOfFilters)) {
if (!typeOfFilters[f]) {
return true;
}
if (
f === "currency" &&
typeOfFilters["frequency"].indexOf(plan[f]) > -1
) {
return true;
}
if (f === "currency" && typeOfFilters[f].indexOf(plan[f]) > -1) {
return true;
}
if (plan[f] === undefined || plan[f] !== typeOfFilters[f]) {
return false;
}
}
});
```
expected output should return the table entry which has the frequency inside typeOfFilter['frequency']
Upvotes: 1
Views: 339
Reputation: 607
I believe you're trying to filter the data based on multiple filters and assuming that the individual filter can also have multiple values. For example: if currency
filter is ['USD', 'INR']
then you're expecting plans of both currency type.
I updated the typeOfFilters
object as follows so that each filter can have a basic initial state:
const typeOfFilters = {
"currency": [],
"frequency": [],
"provider": [],
"amount": 0,
"status": [],
}
And based on that here's the final function:
let sortedTableArray = plans.filter(plan => {
for (let f in typeOfFilters) {
// Tests for all array type filters
if (typeOfFilters[f] instanceof Array && typeOfFilters[f].length == 0) {
continue
}
if (typeOfFilters[f] instanceof Array && typeOfFilters[f].indexOf(plan[f]) == -1){
return false;
}
// Test for amount filter
if (typeof typeOfFilters[f] === "number" && plan[f] < typeOfFilters[f]) {
return false;
}
}
return true
});
Upvotes: 1
Reputation: 6887
let plans = [
{
"amount": 6000,
"currency": "USD",
"frequency": "MONTH",
"planId": "plan_L7mrzVML9o6G5c",
"planName": "computer",
"provider": "stripe"
},
{
"amount": 2000,
"currency": "INR",
"frequency": "DAY",
"planId": "plan_KkHkJPEVR7ZA2s",
"planName": "Platinum",
"provider": "stripe"
}
]
let plansWithId = plans.map((item)=>{
item.id = guidGenerator();
return item;
});
const typeOfFilters = {
currency: ['INR'],
frequency: ['MONTH'],
provider: "",
amount: "",
status: "",
}
// 1. let your typeOfFilters have values are array. If not use typeof to make sure all are in same format.
//2. add a id value to your plans to avoid duplicates
let output = [];
for(key in typeOfFilters){
let toff = typeOfFilters[key];
if(typeof(toff) === 'string'){
toff = [toff];
}
const onlyvalues = toff.filter(v => v); // filter empty values
if(onlyvalues.length){
temp = plansWithId.filter((item) => {
return onlyvalues.indexOf(item[key]) !== -1;
});
output = output.concat(temp);
}
}
const selectedIds = [];
const duplicatesRemoved = output.filter((item) => {
if(selectedIds.indexOf(item.id) !== -1){
return false;
}
selectedIds.push(item.id);
return true;
})
console.log(duplicatesRemoved)
function guidGenerator() {
var S4 = function() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}
The approach is difference in this solution. The typeOfFilters are looped first and if it matches with any in plans, the output will be generated.
Note: This is based on OR condition. so any filter matches, it will provide the output.
Upvotes: 0
Reputation: 464
I am not entirely sure what you are trying to accomplish here, but the iteration does not fail. It is just interrupted by your last check:
if (plan[f] === undefined || plan[f] !== typeOfFilters[f]) {
return false;
}
More specifically by:
plan[f] !== typeOfFilters[f]
The first filter that is checked is this one:
currency: ['INR']
And plan[f] might be 'INR', but it is not ['INR']. So this check will always fail. Therefore the filter returns false and it moves on to the next plan.
What I believe you might be after is something like this:
const plans = [
{
amount: 6000,
currency: "USD",
frequency: "MONTH",
planId: "plan_L7mrzVML9o6G5c",
planName: "computer",
provider: "stripe",
},
{
amount: 2000,
currency: "INR",
frequency: "DAY",
planId: "plan_KkHkJPEVR7ZA2s",
planName: "Platinum",
provider: "stripe",
},
];
const typeOfFilters = {
currency: ['INR'],
frequency: ['DAY'],
provider: "",
amount: "",
status: "",
};
const sortedTableArray = plans.filter(plan => {
for (const [f, value] of Object.entries(typeOfFilters)) {
if (value) {
if (Array.isArray(value) && value.includes(plan[f])) {
return true;
} else if (plan[f] === value) {
return true;
}
}
}
});
console.log(sortedTableArray);
Upvotes: 0