Reputation: 9830
I am trying to create a filter that is working when the object is a single value, but when introducing an array of keywords I am having issues.
My code looks like the following:
const filter = {
colors: ["white"],
sizes: [9, 12],
brands: ["adidas"],
keywords: ["running", "weights"]
};
const shoes = [{
brand: "adidas",
size: 9,
color: "white",
keywords: ["running"]
},
{
brand: "adidas",
size: 12,
color: "white",
keywords: ["weigths"]
},
{
brand: "nike",
size: 7,
color: "red",
keywords: ["running", "tennis"]
}
];
const properties = {
colors: 'color',
sizes: 'size',
brands: 'brand',
keywords: 'keywords',
}
const filters = Object
.entries(filter)
.filter(([, {
length
}]) => length)
.map(([k, v]) => [properties[k], v]);
const result = shoes.filter(shoe => filters.every(([k, v]) => v.includes(shoe[k])));
console.log('result', result)
The result that I am looking for is
const results = {
brand: "nike",
size: 9,
color: "white",
keywords: ["running"]
},
{
brand: "adidas",
size: 12,
color: "white",
keywords: ["swimming"]
}]
Upvotes: 0
Views: 95
Reputation: 386868
By having matching words withou spellin g differences, you could create an array of every value and check against the wanted values.
const
filter = { colors: ["white"], sizes: [9, 12], brands: ["adidas"], keywords: ["running", "weights"] },
shoes = [{ brand: "nike", size: 9, color: "white", keywords: ["running"] }, { brand: "adidas", size: 12, color: "white", keywords: ["weights"] }, { brand: "nike", size: 7, color: "red", keywords: ["running", "tennis"] }],
properties = { colors: 'color', sizes: 'size', brands: 'brand', keywords: 'keywords' },
filters = Object
.entries(filter)
.filter(([, { length }]) => length)
.map(([k, v]) => [properties[k], v]),
result = shoes.filter(
shoe => filters.every(
([k, v]) => [].concat(shoe[k]).some(value => v.includes(value))
)
);
console.log('result', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 1168
The following should take filter out any object that has a value inconsistent with the filters:
const filterObjectArray = (filters, array) => {
return array.filter(obj => {
// iterate through each key in filters
for (let i in filters) {
const objVal = obj[properties[i]]
// here, we can use flatMap to "spread" objVal and filters[i] into
// an array, whether or not objVal is an array
const combinedValues = [objVal, filters[i]].flatMap(x => x)
// convert the combinedValues into a Set to remove duplicates
const set = new Set(combinedValues)
// If the size of the set matches the length of combinedValues
// it means that objVal and filters[i] have no values in common, so we
// can just return false.
if (set.size === combinedValues.length) return false
}
// If we reach here, it means every value in object has been validated by every key/value in filters.
return true
})
}
Here's a repl where you can see this code in action: https://replit.com/@isaacsan123/filtering-objects
Upvotes: 0
Reputation: 3920
My assumption, you are filtering by size
, color
and keywords
not by brand
and based on that I produced the code below, but if the assumption is not valid please provide more details
You can use array.filter
to filter an array by passing conditions
let result = shoes.filter(f => filter.sizes.includes(f.size)
&& filter.colors.includes(f.color)
&& filter.keywords.some(k => f.keywords.includes(k))
)
console.log(result);
Upvotes: 0