i've got this example of code. Data is my current data which i show in view, and selectedOptions is a object that contains currently selected options by keys.
const data = {
names: [
{ key: 1, name: 'Marek' },
{ key: 2, name: 'Marek 2' },
{ key: 3, name: 'Marek 3' },
{ key: 4, name: 'Marek 4' },
],
ages: [
{ key: 1, age: 14 },
{ key: 2, age: 11 },
{ key: 3, age: 17 },
{ key: 4, age: 22 },
{ key: 5, age: 31 },
],
};
const selectedOptions = {
names: [1, 2],
ages: [4],
};
const showResults = () => {};
showResults();
And I need to filter current data to selected options by key. Final result should be like this:
const filteredData = {
names: [
{ key: 1, name: 'Marek' },
{ key: 2, name: 'Marek 2' },
],
ages: [
{ key: 4, age: 22 },
],
};
CodePudding user response:
The OP's target data structure not only corresponds to the one of the original data but also repeats itself with the OP's selectedOptions
which for better understanding will be referred to from now as selectedKeyValues
.
Thus, since the OP wants to build a new structure similar to the above two mentioned, the OP needs to map
the entries
of selectedKeyValues
(FKA selectedOptions
).
For a better understanding the result of the last mentioned (but first to be performed) task will be logged ...
const selectedKeyValues = {
names: [1, 2],
ages: [4],
};
console.log(
Object
.entries(selectedKeyValues)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
A map
task now has access to a data entry's key and the array of key-values. Via the key one can access the original data's entry. In case it exists one could build a Map
-based lookup for any of said entry's item, based on such an item's "key"
property.
The advantage of a lookup comes with not needing to always iterate (e.g. via includes
) the same items array (especially the ones with a huge amount of items) again and again for each item key's value.
The same map
task then creates and returns an object with a sole property where the name equals the data entry's key, and the value will be an array of filtered original data-entry items where the filtered array is collected via a reduce
task which concat
enates the looked up (thus matching by key-value) items.
const data = {
names: [
{ key: 1, name: 'Marek' },
{ key: 2, name: 'Marek 2' },
{ key: 3, name: 'Marek 3' },
{ key: 4, name: 'Marek 4' },
],
ages: [
{ key: 1, age: 14 },
{ key: 2, age: 11 },
{ key: 3, age: 17 },
{ key: 4, age: 22 },
{ key: 5, age: 31 },
],
};
const selectedKeyValues = {
names: [1, 2],
ages: [4],
};
const selectedData = Object
.entries(selectedKeyValues)
.map(([entryKey, valuesOfItemKeys]) => {
const itemLookup = new Map(
(data[entryKey] ?? [])
.map((item) => [item.key, item])
);
return {
[ entryKey ]: valuesOfItemKeys
.reduce((filteredItems, itemKeyValue) => {
return filteredItems.concat(
itemLookup.get(itemKeyValue) ?? []
);
}, []),
};
});
console.log({
selectedData
});
.as-console-wrapper { min-height: 100%!important; top: 0; }
CodePudding user response:
const data = {
names: [
{ key: 1, name: 'Marek' },
{ key: 2, name: 'Marek 2' },
{ key: 3, name: 'Marek 3' },
{ key: 4, name: 'Marek 4' },
],
ages: [
{ key: 1, age: 14 },
{ key: 2, age: 11 },
{ key: 3, age: 17 },
{ key: 4, age: 22 },
{ key: 5, age: 31 },
],
};
const selectedOptions = {
names: [1, 2],
ages: [4],
};
const filterSelectedDataItems = (data, selectedOptions) => {
const filteredData = {};
for (const key in data) {
filteredData[key] = data[key].filter((i) =>
selectedOptions[key].includes(i.key)
);
}
return filteredData;
};
const selectedData = filterSelectedDataItems(data, selectedOptions);
console.log({ selectedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
this works.