Home > OS >  better way to handle these arrays
better way to handle these arrays

Time:02-27

I have a menu with 3 groups of check boxes that will be used to filter items on a page. They are store, city and level. Checking any box in any of the groups add the value to the corresponding array in an object that looks like this:

items = {
  store: [],
  city: [],
  level: []
}

The default is for all items to be visible and no check boxes checked. When boxes are checked, only the items corresponding to

Each time a box is checked or unchecked, the items are filtered. First the items are filtered by store and city and then that sub-set of items is further filtered by level. If no level boxes are checked, all levels are displayed, but if any are checked, only checked store/citys of the checked levels are displayed.

So my object can look like this

itms = {
  store: [
    'north',
    'evans',
    'dodge'
  ],
  city: [
    'boston',
    'miami',
  ],
  level: [
    'gold',
    'silver'
  ]
}

In the end, I need a string that looks like this:
.north.gold,.north.silver,.evans.gold,.evans.silver,.dodge.gold,.dodge.silver,.boston.gold,.boston.silver,.miami.gold,.miami.silver, - order doesn't matter

If my object looked like this:

items = {
  store: [
    'north',
    'evans',
    'dodge'
  ],
  cite: [ 'miami' ],
  level: []
}

I'd need a string that looks like this:
.north,.evans,.dodge,.miami

Hopefully, you get the gist...

To derive the properly formatted string from the object, I'm doing some, what I'm pretty sure is horribly inefficient, iterating:

      for (let [key, value] of Object.entries(items)) {
        value.forEach(item => {
          if(key !== 'level') {
            finalSelectors.push(`.${item}`);
            if (key === 'city') {
              finalSelectors.push(`.${item}_child`);
            }
          }
        });
      }
      
      let selectorsArr = finalSelectors;
      const reFinalSelectors = [];
      const selectedLevels = items.level;
      if(selectedLevels.length) {
        if(items.city.length || items.location.length) {
          finalSelectors.forEach(selector => {
            selectedLevels.forEach(level => {
              reFinalSelectors.push(`.${level}${selector}`);
            });
          });
        } else {
          selectedLevels.forEach(level => {
            reFinalSelectors.push(`.${level}`);
          });
        }
        selectorsArr = reFinalSelectors; 
      }

I don't even know where to begin to do this more efficiently as I am just starting to learn how to use array functions and don't have too good of a grasp of the more advanced ones like Array.reduce(). Any hints or help would be greatly appreciated.

CodePudding user response:

It looks like the store and city arrays are treated identically for the purposes of the algorithm, so you can put them together. Then all you need to do is match each of those with each level - an easy two-dimensional iteration.

The only complication is that if there isn't anything in level, to push only the prefix (store/city) instead of iterating over the level.

const items = {
  store: [
    'north',
    'evans',
    'dodge'
  ],
  city: [
    'boston',
    'miami',
  ],
  level: [
    'gold',
    'silver'
  ]
};

const { level } = items;
const resultArr = [];
for (const prefix of items.store.concat(items.city)) {
  if (level.length) {
    for (const suffix of level) {
      resultArr.push(`.${prefix}.${suffix}`);
    }
  } else {
    resultArr.push(`.${prefix}`);
  }
}
console.log(resultArr.join(','));

  • Related