Reputation:
I am trying to make a filter for this information, this is an array of objects from a API with the information of all the products in the database, in this example I only show one product, but the API request all products.
[
{
"Id": 11,
"Name": "Papas fritas",
"Description": "Papas",
"Availability": 1,
"Price": 1,
"Stock": 10,
"Promotion": 0,
"Discount": 0,
"Visible": 1,
"CreationDate": "2021-04-22T18:51:51.000Z",
"UpdateAt": null,
"Photo": [
{
"Id": 21,
"Photo": "photo.png"
}
],
"Rating": 4.5,
"Category": [
{
"Id": 2,
"Category": "Moda",
"Icon": "Fashion"
},
{
"Id": 3,
"Category": "Fitness",
"Icon": "Fitness"
}
],
"Subcategory": [],
"Characteristics": [],
}
Now I make a class that have the methods for short and filter this array, but I have a problem filtering the information, I don't know how to filter the information by category using something like this:
[{Category: 'Art,Fitnness'}]
It's also is possible that the Promotion
property will be formatted this way:
[{Promotion: 'true'}]
As you can see this array with the filters can have more than one property and can be a different property than category i need to validate the values because all values in the array are strings and sometimes Array.filter doesn't work comparing a string "true" === 1
What I implement for this is this function, query is the array of the products and queryvalues is the filter array
FilterFuntion(Query, QueryValues)
{
QueryValues = Object.entries(QueryObj).map((e) => ( { [e[0]]: e[1] } ));
let FilteredArray = Query;
QueryValues.map((Filter) =>
{
var key = Object.keys(Filter)[0];
FilteredArray = ValidateFilter(key, Filter[key], FilteredArray);
});
return FilteredArray;
}
ValidateFilter(Key, Value, array)
{
return array.filter((El) =>
{
if (Value === "true" || Value === "false")
{
return Boolean(El[Key]) === Boolean(Value);
}
if(Array.isArray((El[Key]))
{
(El[Key]).filter((sub) =>
{
return String(sub[Key]) === String(Value);
});
}
return String(El[Key]) === String(Value);
});
}
So I validate if the value of the filter is a bool string or int first and next I return the value that match, that work correct whit all the normal values but when the value nested in another array doesn't work, it returns a filter array of category instead of return the entire product, I don't know how to make this work when there are nested arrays, and when I would want to filter on multiple categories, how can I do it ?.
[{Category: 'Art,Fitnness'}]
Another thing is for example when the filter has a value between two numbers, for example look Rating property, I need to filter and return only the products that have a rating between 5 and 4
[{Promotion: 'true'}, {Category: 'Fitness'}, {Rating: '5,4'}]
Upvotes: 1
Views: 496
Reputation: 23664
Using filter
, we can take each object from the array and test whether or not it meets the criteria.
Here is the anatomy of the filter object:
filter = {
Rating: [3, 5],
Category: [
['Fitness','Moda'],
['OtherCategory']
],
Promotion: 'false'
}
Rating is an array for 'between' - if you're looking for an exact number, just put it in twice ([4.5,4.5]
). Category is an array of arrays and takes care of or/and
like this:
[
['Fitness','Moda'], // product has both categories 'Fitenss' and 'Moda'
['OtherCategory'] // OR product has 'OtherCategory'
]
const data = [{
"Id": 11,
"Name": "Papas fritas",
"Description": "Papas",
"Availability": 1,
"Price": 1,
"Stock": 10,
"Promotion": 0,
"Discount": 0,
"Visible": 1,
"CreationDate": "2021-04-22T18:51:51.000Z",
"UpdateAt": null,
"Photo": [{
"Id": 21,
"Photo": "photo.png"
}],
"Rating": 4.5,
"Category": [{
"Id": 2,
"Category": "Moda",
"Icon": "Fashion"
},
{
"Id": 3,
"Category": "Fitness",
"Icon": "Fitness"
}
],
"Subcategory": [],
"Characteristics": []
},
{
"Id": 13,
"Name": "Papas fritas2",
"Description": "Papas2",
"Availability": 1,
"Price": 1,
"Stock": 10,
"Promotion": 0,
"Discount": 0,
"Visible": 1,
"CreationDate": "2021-04-22T18:51:51.000Z",
"UpdateAt": null,
"Photo": [{
"Id": 21,
"Photo": "photo.png"
}],
"Rating": 3.5,
"Category": [{
"Id": 2,
"Category": "OtherCategory",
"Icon": "Fashion"
}],
"Subcategory": [],
"Characteristics": []
}
]
//[{Promotion: 'true'}, {Category: 'Fitness'}, {Rating: '5,4'}]
const filterProductsBy = (criteria, data) => {
let p = data.filter(obj => {
let isMatch = true;
if (criteria.Rating && (obj.Rating < criteria.Rating[0] || obj.Rating > criteria.Rating[1])) isMatch = false;
if (criteria.Category) {
let catMatch = false
// prepare the cat array
let cats = obj.Category.map(c => c.Category);
criteria.Category.forEach(set =>
set.forEach(catAnd => {
console.log(cats, catAnd, cats.includes(catAnd))
if (cats.includes(catAnd)) catMatch = true;
})
)
if (!catMatch) isMatch = false;
}
if (criteria.Subcategory) {
let catMatch = false
// prepare the Subcategory array
let subcats = obj.Subcategory.map(c => c.Subcategory);
criteria.Subcategory.forEach(set =>
set.forEach(catAnd => {
//console.log(subcats, catAnd, subcats.includes(catAnd))
if (subcats.includes(catAnd)) catMatch = true;
})
)
if (!catMatch) isMatch = false;
}
obj.Promotion = obj.Promotion === 0 ? 'false' : 'true';
if (criteria.Promotion && obj.Promotion != criteria.Promotion) isMatch = false;
return isMatch;
})
return p
}
let filter = {
Rating: [3, 5],
Category: [
['Fitness']
],
Promotion: 'false'
}
console.log(filterProductsBy(filter, data))
filter = {
Rating: [3, 5],
Category: [
['Fitness'],
['OtherCategory']
],
Promotion: 'false'
}
console.log(filterProductsBy(filter, data))
Upvotes: 1