I'm struggling with a interactive search filter in VueJS (It's a app with drop downs and ranges @ codepen)
A boat has BrandName, BrandYear, Price... which I've been able to filter through using selected = {...}
, but I wonder how to make the best usage of this if-statement
below, to identify the Price and check min/max and return results by passing expected_selected = {...}
I'm looking for explanation/help on how I can filter a min/max value together with the following code.
Goal is to input a minimuma and maximum value together with one or more matched key values
var boats = [{
Price: 599900,
BrandName: "FLIPPER",
BoatYear: 2020,
}, {
Price: 97e3,
BrandName: "MICORE",
BoatYear: 2020,
}, {
Price: 189300,
BrandName: "LINDER",
BoatYear: 2020,
}, {
Price: 396900,
BrandName: null,
BoatYear: 2020,
}, {
Price: 334900,
BrandName: "MICORE",
BoatYear: 2019,
}, {
Price: 138700,
BrandName: "HR",
BoatYear: 2020,
}, {
Price: 178900,
BrandName: "HR",
BoatYear: 2020,
}, {
Price: 348900,
BrandName: "HR",
BoatYear: 2020,
}, {
Price: 285800,
BrandName: "HR",
BoatYear: 2020,
}, {
Price: 186900,
BrandName: "MICORE",
BoatYear: 2019,
}, {
Price: 276800,
BrandName: "MICORE",
BoatYear: 2020,
}, {
Price: 518900,
BrandName: "SILVER",
BoatYear: 2020,
}, {
Price: 226900,
BrandName: "MICORE",
BoatYear: 2020,
}, {
Price: 132600,
BrandName: "LINDER",
BoatYear: 2020,
}, {
Price: 137200,
BrandName: "LINDER",
BoatYear: 2020,
}, {
Price: 366900,
BrandName: "SILVER",
BoatYear: 2020,
}, {
Price: 365900,
BrandName: "SILVER",
BoatYear: 2020,
}, {
Price: 247900,
BrandName: "SILVER",
BoatYear: 2020,
}];
var selected = {
BoatYear: 2020,
BrandName: "LINDER"
};
var expected_selected = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: [0, 138000] // min , max
}
boats = boats.filter(function(item) {
for (var key in selected) {
if (item[key] === undefined || item[key] != selected[key]) return false;
}
return true;
});
console.log(`Results: ${JSON.stringify(boats)}`);
To filter JSON data with multiple objects, you can use the concept of filter along with ==.
If you want to put multiple conditions in filter , you can use && and || operator.
JSON array are ordered list of values. JSON arrays can be of multiple data types. JSON array can store string , number , boolean , object or other array inside JSON array. In JSON array, values must be separated by comma.
let boats = [
{Price: 599900, BrandName: "FLIPPER", BoatYear: 2020},
{Price: 97e3 , BrandName: "MICORE" , BoatYear: 2020},
{Price: 189300, BrandName: "LINDER" , BoatYear: 2020},
{Price: 396900, BrandName: null , BoatYear: 2020},
{Price: 334900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 138700, BrandName: "HR" , BoatYear: 2020},
{Price: 178900, BrandName: "HR" , BoatYear: 2020},
{Price: 348900, BrandName: "HR" , BoatYear: 2020},
{Price: 285800, BrandName: "HR" , BoatYear: 2020},
{Price: 186900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 276800, BrandName: "MICORE" , BoatYear: 2020},
{Price: 518900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 226900, BrandName: "MICORE" , BoatYear: 2020},
{Price: 132600, BrandName: "LINDER" , BoatYear: 2020},
{Price: 137200, BrandName: "LINDER" , BoatYear: 2020},
{Price: 366900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 365900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 247900, BrandName: "SILVER" , BoatYear: 2020}
];
const expected_selected = {
BoatYear : 2020,
BrandName: 'LINDER',
Price : { min: 0, max: 138000 },
}
const filter_by = filters => item => {
if (item.BoatYear === undefined || item.BoatYear !== filters.BoatYear ) return false
if (item.BrandName === undefined || item.BrandName !== filters.BrandName ) return false
if (item.Price < filters.Price.min || item.Price > filters.Price.max) return false
return true
}
boats = boats.filter(filter_by(expected_selected))
console.log(`Results: ${JSON.stringify(boats)}`);
let boats = [
{Price: 599900, BrandName: "FLIPPER", BoatYear: 2020},
{Price: 97e3 , BrandName: "MICORE" , BoatYear: 2020},
{Price: 189300, BrandName: "LINDER" , BoatYear: 2020},
{Price: 396900, BrandName: null , BoatYear: 2020},
{Price: 334900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 138700, BrandName: "HR" , BoatYear: 2020},
{Price: 178900, BrandName: "HR" , BoatYear: 2020},
{Price: 348900, BrandName: "HR" , BoatYear: 2020},
{Price: 285800, BrandName: "HR" , BoatYear: 2020},
{Price: 186900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 276800, BrandName: "MICORE" , BoatYear: 2020},
{Price: 518900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 226900, BrandName: "MICORE" , BoatYear: 2020},
{Price: 132600, BrandName: "LINDER" , BoatYear: 2020},
{Price: 137200, BrandName: "LINDER" , BoatYear: 2020},
{Price: 366900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 365900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 247900, BrandName: "SILVER" , BoatYear: 2020},
]
const expected_selected = {
BoatYear : { min: 2020 , max: 2020 },
BrandName: { min: 'LINDER', max: 'LINDER' },
Price : { min: 0 , max: 138000 },
}
const filter_by = filters => item => {
for (var key in filters) {
if (item[key] === undefined) return false
if (item[key] < filters[key].min || item[key] > filters[key].max) return false
}
return true
}
boats = boats.filter(filter_by(expected_selected))
console.log(`Results: ${JSON.stringify(boats)}`);
selected
field (in this case Array.isArray
, in case of {min,max}
it would be instanceof
)let boats = [
{Price: 599900, BrandName: "FLIPPER", BoatYear: 2020},
{Price: 97e3 , BrandName: "MICORE" , BoatYear: 2020},
{Price: 189300, BrandName: "LINDER" , BoatYear: 2020},
{Price: 396900, BrandName: null , BoatYear: 2020},
{Price: 334900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 138700, BrandName: "HR" , BoatYear: 2020},
{Price: 178900, BrandName: "HR" , BoatYear: 2020},
{Price: 348900, BrandName: "HR" , BoatYear: 2020},
{Price: 285800, BrandName: "HR" , BoatYear: 2020},
{Price: 186900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 276800, BrandName: "MICORE" , BoatYear: 2020},
{Price: 518900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 226900, BrandName: "MICORE" , BoatYear: 2020},
{Price: 132600, BrandName: "LINDER" , BoatYear: 2020},
{Price: 137200, BrandName: "LINDER" , BoatYear: 2020},
{Price: 366900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 365900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 247900, BrandName: "SILVER" , BoatYear: 2020},
]
const expected_selected = {
BoatYear : 2020,
BrandName: 'LINDER',
Price : [ 0, 138000 ],
}
const filter_by = filters => item => {
for (var key in filters) {
if (item[key] === undefined) return false
if (Array.isArray(filters[key])) {
if(item[key] < filters[key][0] || item[key] > filters[key][1]) return false
} else if (item[key] !== filters[key]) return false
}
return true
}
boats = boats.filter(filter_by(expected_selected))
console.log(`Results: ${JSON.stringify(boats)}`);
let boats = [
{Price: 599900, BrandName: "FLIPPER", BoatYear: 2020},
{Price: 97e3 , BrandName: "MICORE" , BoatYear: 2020},
{Price: 189300, BrandName: "LINDER" , BoatYear: 2020},
{Price: 396900, BrandName: null , BoatYear: 2020},
{Price: 334900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 138700, BrandName: "HR" , BoatYear: 2020},
{Price: 178900, BrandName: "HR" , BoatYear: 2020},
{Price: 348900, BrandName: "HR" , BoatYear: 2020},
{Price: 285800, BrandName: "HR" , BoatYear: 2020},
{Price: 186900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 276800, BrandName: "MICORE" , BoatYear: 2020},
{Price: 518900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 226900, BrandName: "MICORE" , BoatYear: 2020},
{Price: 132600, BrandName: "LINDER" , BoatYear: 2020},
{Price: 137200, BrandName: "LINDER" , BoatYear: 2020},
{Price: 366900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 365900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 247900, BrandName: "SILVER" , BoatYear: 2020},
]
class MinMax {
constructor(min, max) { this.min = min, this.max = max }
check(val) { return val >= this.min && val <= this.max }
}
class Eq {
constructor(val) { this.val = val }
check(val) { return val === this.val }
}
var expected_selected = {
BoatYear : new Eq(2020),
BrandName: new Eq('LINDER'),
Price : new MinMax(0, 138000)
}
const filter_by = filters => item => {
for (var key in filters) {
if (item[key] === undefined) return false
if (filters[key].check(item[key]) === false) return false
}
return true
}
boats = boats.filter(filter_by(expected_selected))
console.log(`Results: ${JSON.stringify(boats)}`);
This way you can extend your filters by adding new classes without changing filter_by
function.
Checking objects using key arrays makes sense when we have many properties to validate. In your case you have 4 properties that you need to be check by equality and 3 properties that need to be checked by range, so, if you want to "Don't Repeat Yourself", you can do it using key arrays like in your example and in your project.
You can create a key array for each type you want to check and then validate all these conditions inside a single filter going through all keys. For this example, you'll have an array with keys for the values that need to be checked by equality and one array with keys for values that need to be checked by integer min/max range:
let boats = [
{Price:599900, BrandName:"FLIPPER", BoatYear:2020},
{Price:97000, BrandName:"MICORE", BoatYear:2020},
{Price:189300, BrandName:"LINDER", BoatYear:2020},
{Price:396900, BrandName:null, BoatYear:2020},
{Price:334900, BrandName:"MICORE", BoatYear:2019},
{Price:138700, BrandName:"HR", BoatYear:2020},
{Price:178900, BrandName:"HR", BoatYear:2020},
{Price:348900, BrandName:"HR", BoatYear:2020},
{Price:285800, BrandName:"HR", BoatYear:2020},
{Price:186900, BrandName:"MICORE", BoatYear:2019},
{Price:276800, BrandName:"MICORE", BoatYear:2020},
{Price:518900, BrandName:"SILVER", BoatYear:2020},
{Price:226900, BrandName:"MICORE", BoatYear:2020},
{Price:132600, BrandName:"LINDER", BoatYear:2020},
{Price:137200, BrandName:"LINDER", BoatYear:2020},
{Price:366900, BrandName:"SILVER", BoatYear:2020},
{Price:365900, BrandName:"SILVER", BoatYear:2020},
{Price:247900, BrandName:"SILVER", BoatYear:2020}
];
let expected = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: [0, 138000] // min, max
}
// Keys that need to be checked by equality
const equals = ['BrandName', 'BoatYear', /* 'MotoBoatType', 'EngineModel' */];
// Keys that need to be checked by range
const ranges = ['Price', /* 'Width', 'Length' */]
boats = boats.filter((item) => {
// First check the equality keys
for (const field of equals)
if (expected[field] && item[field] !== expected[field]) return false;
// Then check the range keys
for (const field of ranges)
if (item[field] < expected[field][0] || item[field] > expected[field][1]) return false;
return true;
});
console.log(`Results: ${boats.length}`,
boats.map(({ Price, BrandName, BoatYear }) => `${BrandName} (${BoatYear}) : ${Price}`)
);
You can even make the filter code just 2 lines using Array.prototype.every()
to validate the array keys:
let boats = [
{Price:599900, BrandName:"FLIPPER", BoatYear:2020},
{Price:97000, BrandName:"MICORE", BoatYear:2020},
{Price:189300, BrandName:"LINDER", BoatYear:2020},
{Price:396900, BrandName:null, BoatYear:2020},
{Price:334900, BrandName:"MICORE", BoatYear:2019},
{Price:138700, BrandName:"HR", BoatYear:2020},
{Price:178900, BrandName:"HR", BoatYear:2020},
{Price:348900, BrandName:"HR", BoatYear:2020},
{Price:285800, BrandName:"HR", BoatYear:2020},
{Price:186900, BrandName:"MICORE", BoatYear:2019},
{Price:276800, BrandName:"MICORE", BoatYear:2020},
{Price:518900, BrandName:"SILVER", BoatYear:2020},
{Price:226900, BrandName:"MICORE", BoatYear:2020},
{Price:132600, BrandName:"LINDER", BoatYear:2020},
{Price:137200, BrandName:"LINDER", BoatYear:2020},
{Price:366900, BrandName:"SILVER", BoatYear:2020},
{Price:365900, BrandName:"SILVER", BoatYear:2020},
{Price:247900, BrandName:"SILVER", BoatYear:2020}
];
let expected = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: [0, 138000] // min, max
}
const equals = ['BrandName', 'BoatYear', /* 'MotoBoatType', 'EngineModel' */];
const ranges = ['Price', /* 'Width', 'Length' */]
boats = boats.filter((item) =>
equals.every(field => !expected[field] || item[field] === expected[field]) &&
ranges.every(field => item[field] >= expected[field][0] && item[field] <= expected[field][1])
);
console.log(`Results: ${boats.length}`,
boats.map(({ Price, BrandName, BoatYear }) => `${BrandName} (${BoatYear}) : ${Price}`)
);
You can check this working on the fork I made from you demo project on Codepen. It has the same method and it applies the validation to all the range keys Price
, Width
and Length
.
You already might have got the solution, but just to put my thought over here I'm posting this answer. I have created a generic function which will take an object(filter object) which can have values with primitives, or object or an array. Hope this helps
let boats = [
{Price: 599900, BrandName: "FLIPPER", BoatYear: 2020},
{Price: 97e3 , BrandName: "MICORE" , BoatYear: 2020},
{Price: 189300, BrandName: "LINDER" , BoatYear: 2020},
{Price: 396900, BrandName: null , BoatYear: 2020},
{Price: 334900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 138700, BrandName: "HR" , BoatYear: 2020},
{Price: 178900, BrandName: "HR" , BoatYear: 2020},
{Price: 348900, BrandName: "HR" , BoatYear: 2020},
{Price: 285800, BrandName: "HR" , BoatYear: 2020},
{Price: 186900, BrandName: "MICORE" , BoatYear: 2019},
{Price: 276800, BrandName: "MICORE" , BoatYear: 2020},
{Price: 518900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 226900, BrandName: "MICORE" , BoatYear: 2020},
{Price: 132600, BrandName: "LINDER" , BoatYear: 2020},
{Price: 137200, BrandName: "LINDER" , BoatYear: 2020},
{Price: 366900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 365900, BrandName: "SILVER" , BoatYear: 2020},
{Price: 247900, BrandName: "SILVER" , BoatYear: 2020}
];
var expected_selected = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: [0, 138000] // min , max
}
var expected_selected_2 = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: {min:0, max:138000}
}
var expected_selected_3 = {
BoatYear: 2020,
BrandName: 'LINDER',
Price: 137200
}
const filter_by = (filter) => item => {
for(let key in filter) {
if(filter.hasOwnProperty(key)){
if(Array.isArray(filter[key])) {
if(!item[key] || item[key] < filter[key][0] || item[key] > filter[key][1]) return false;
}
else if(typeof filter[key] === "object") {
if(!item[key] || item[key] < filter[key]["min"] || item[key] > filter[key]["max"]) return false;
}
else {
if(!item[key] || item[key] !== filter[key]) return false;
}
} else {
return false
}
}
return true
}
const results = boats.filter(filter_by(expected_selected))
console.log(`Results: ${JSON.stringify(results, null, 2)}`);
const results_2 = boats.filter(filter_by(expected_selected_2))
console.log(`Results_2: ${JSON.stringify(results_2, null, 2)}`);
const results_3 = boats.filter(filter_by(expected_selected_3))
console.log(`Results_3: ${JSON.stringify(results_3, null, 2)}`);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With