Stack Overflow Asked by frontMaster on January 22, 2021
I have a process which dynamically – depending on checkbox state changes – creates kind of a config
object which describes how the condition for filtering an array of data-items should be built.
A filter configuration might look like this one …
const filter = {
publicationType: ['type-1', 'type-2'],
termType: ['term-1', 'term-2'],
reportFormat: ['xml'],
}
A simplified list of data items then looks like that …
const data = [
{ id: 1, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-1' },
{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' },
{ id: 3, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-2' },
]
I would like the condition to match every category/type (a configuration’s key), but its value can be either one from a category’s/type’s array.
From the provided example data and specifications the expected filter result would be …
[{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' }]
How does an approach look like which builds a correct filter condition based on the provided filter
configuration object.
Below is my attempt to make a filter function but filtering works properly only on single Select component, if I try to filter on multiple Select components – data duplicates.
const handleFilter = (val) => {
const filterKeys = Object.keys(val);
const filteredStats = [];
// loop objects in fetched arr
for (const item of stat) {
// loop properties by which filtering data
filterKeys.forEach((keys) => {
// check if data property match with a filtering property in array
const isPresent = val[keys].some((key) => {
const statProperty = item[keys];
const filterProperty = key;
return filterProperty === statProperty;
});
if (isPresent) {
filteredStats.push(item);
}
});
}
setfilteredState(filteredStats);
};
https://codesandbox.io/s/checkbox-filter-vqex7?file=/src/App.js
One of the approache's base techniques is taking advantage of the fact that almost every Array
method allows for an additionally passed target
object which the solution utilizes with e.g. Array.prototype.filter
and Array.prototype.every
The main approach is reading and applying the filter configuration for every iteration of the data array's filter
method.
This function needs to iterate every
key-value(List) pair of a configuration's entries
for checking whether a specific data-item matches a specifically configured condition-entry.
The latter task is done by another function which can access the data-item and does "know" both, this data-item's currently to be checked for property-key and the list of possibly valid property-values, which makes it easy to check for whether some
of the final condition(s) do(es) apply.
There is still an edge case, empty value lists, which need to be handled by the latter function. Since the truthiness of its checking relies on some
... (and some
's default return value for empty arrays is false
... [].some(x => true) === false
) ... one has to handle this scenario separately by explicitly returning true
for its fulfilled precondition of valueList.length === 0
.
function doesBoundItemMatchConditionEntry([key, valueList]) {
const item = this;
const itemValue = item[key];
return ((
valueList.length === 0
) || (
item.hasOwnProperty(key) &&
valueList.some(value => value === itemValue)
));
}
function doesItemMatchConditionsOfBoundConfig(item) {
// const config = this;
return Object
.entries(this)
.every(doesBoundItemMatchConditionEntry, item);
}
const filterConfig = {
publicationType: ['type-1', 'type-2'],
termType: ['term-1', 'term-2'],
reportFormat: ['xml'],
}
const sampleData = [
{ id: 1, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-1' },
{ id: 2, reportFormat: 'xml', termType: 'term-2', publicationType: 'type-2' },
{ id: 3, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-2' },
{ id: 4, reportFormat: 'txt', termType: 'term-2', publicationType: 'type-1' },
{ id: 5, reportFormat: 'xml', termType: 'term-1', publicationType: 'type-2' },
{ id: 6, reportFormat: 'txt', termType: 'term-1', publicationType: 'type-2' },
]
console.log(
'sampleData.filter(doesItemMatchConditionsOfBoundConfig, filterConfig) ...',
sampleData.filter(doesItemMatchConditionsOfBoundConfig, filterConfig)
);
console.log(
`sampleData.filter(doesItemMatchConditionsOfBoundConfig, {
publicationType: ['type-2'],
termType: ['term-1'],
reportFormat: [],
}) ...`,
sampleData.filter(doesItemMatchConditionsOfBoundConfig, {
publicationType: ['type-2'],
termType: ['term-1'],
reportFormat: [],
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Correct answer by Peter Seliger on January 22, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP