Home > Enterprise >  JavaScript: build filters option array by data using Object.fromEntires()
JavaScript: build filters option array by data using Object.fromEntires()

Time:01-08

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');
  •  Tags:  
  • Related