I am trying to build a filtering of objects by their keys and values, the idea is to fill the filters array with keys and values that will not repeat.
For example:
const filters = [{ region_code: [] }, { capital: [] }];
consta data = [{
id: 1,
region_code: 'DE'
capital: 'ABC'
},
{
id: 2,
region_code: 'DE'
capital: 'ABC'
},
{
id: 3,
region_code: 'PL'
capital: 'ZZZ'
}];
And that should have the effect:
const filters = [{ region_code: ['DE', 'PL'] }, { capital: ['ABC', 'ZZZ'] }];
Then I will be able to map these filters at the front and load the appropriate objects using the filter function.
I tried to do it like this:
data.forEach((item) => {
Object.fromEntries(Object.entries(item).map(([k, v]) =>
filters.map(filter => {
filter[k] = v
})
));
});
console.log(filters);
CodePudding user response:
You're never assigning the array created by filter anywhere, and never assigning the object created by fromEntries anywhere. But you don't need either; you already have your objects and arrays, you just need to fill them in. You can do that by looping through the items, getting the region_code and capital of each one, and adding it if it's not already present:
// Get the filter arrays (this code assumes they exist)
const regionFilter = filters.find(element => "region_code" in element).region_code;
const capitalFilter = filters.find(element => "capital" in element).capital;
for (const {region_code, capital} of data) {
if (!regionFilter.includes(region_code)) {
regionFilter.push(region_code);
}
if (!capitalFilter.includes(capital)) {
capitalFilter.push(capital);
}
}
Live Example:
const filters = [{ region_code: [] }, { capital: [] }];
const data = [{
id: 1,
region_code: 'DE',
capital: 'ABC'
},
{
id: 2,
region_code: 'DE',
capital: 'ABC'
},
{
id: 3,
region_code: 'PL',
capital: 'ZZZ'
}];
const regionFilter = filters.find(element => "region_code" in element).region_code;
const capitalFilter = filters.find(element => "capital" in element).capital;
for (const {region_code, capital} of data) {
if (!regionFilter.includes(region_code)) {
regionFilter.push(region_code);
}
if (!capitalFilter.includes(capital)) {
capitalFilter.push(capital);
}
}
console.log(JSON.stringify(filters, null, 4));
.as-console-wrapper {
max-height: 100% !important;
}
That assumes there aren't hundreds of thousands of elements (or more) in the data array, since includes does a linear search. If there are hundreds of thousands of elements and you find that the code above is too slow, you can use a Set to do a more efficient check than includes, like this:
// Get the filter arrays (this code assumes they exist)
const regionFilterElement = filters.find(element => "region_code" in element);
const capitalFilterElement = filters.find(element => "capital" in element);
const knownRegions = new Set(regionFilterElement.region_code);
const knownCapitals = new Set(capitalFilterElement.capital);
for (const {region_code, capital} of data) {
knownRegions.add(region_code);
knownCapitals.add(capital);
}
regionFilterElement.region_code = [...knownRegions];
capitalFilterElement.capital = [...knownCapitals];
Live Example:
const filters = [{ region_code: [] }, { capital: [] }];
const data = [{
id: 1,
region_code: 'DE',
capital: 'ABC'
},
{
id: 2,
region_code: 'DE',
capital: 'ABC'
},
{
id: 3,
region_code: 'PL',
capital: 'ZZZ'
}];
const regionFilterElement = filters.find(element => "region_code" in element);
const capitalFilterElement = filters.find(element => "capital" in element);
const knownRegions = new Set(regionFilterElement.region_code);
const knownCapitals = new Set(capitalFilterElement.capital);
for (const {region_code, capital} of data) {
knownRegions.add(region_code);
knownCapitals.add(capital);
}
regionFilterElement.region_code = [...knownRegions];
capitalFilterElement.capital = [...knownCapitals];
console.log(JSON.stringify(filters, null, 4));
.as-console-wrapper {
max-height: 100% !important;
}
CodePudding user response:
You could reduce the array and build a new object.
const
filters = ['region_code', 'capital'],
data = [{ id: 1, region_code: 'DE', capital: 'ABC' }, { id: 2, region_code: 'DE', capital: 'ABC' }, { id: 3, region_code: 'PL', capital: 'ZZZ' }],
result = Object
.entries(data.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => {
if (!(k in r)) return;
if (!r[k].includes(v)) r[k].push(v);
});
return r;
}, Object.fromEntries(filters.map(k => [k, []]))))
.map(p => Object.fromEntries([p]));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
Try this:
const filters = [{ region_code: [] }, { capital: [] }];
const data = [{ id: 1, region_code: 'DE', capital: 'ABC' }, { id: 2, region_code: 'DE', capital: 'ABC' }, { id: 3, region_code: 'PL', capital: 'ZZZ' }];
data.map(d => {
if (!filters[0].region_code.includes(d.region_code)) {
filters[0].region_code.push(d.region_code)
}
if (!filters[1].capital.includes(d.capital)) {
filters[1].capital.push(d.capital)
}
})
console.log(filters)
CodePudding user response:
You can do it using simple for loop
const data=[{id:1,region_code:"DE",capital:"ABC"},{id:2,region_code:"DE",capital:"ABC"},{id:3,region_code:"PL",capital:"ZZZ"}];
let region_code = [];
let capital = [];
let finalArr = [];
for (let i = 0; i < data.length; i ) {
region_code.push(data[i].region_code);
capital.push(data[i].capital);
}
finalArr.push({ 'region_code': [...new Set(region_code)] }, { 'capital': [...new Set(capital)] })
console.log(finalArr, 'finalArr');
