Home > Software design >  Nested Loop through the two array for sort by category
Nested Loop through the two array for sort by category

Time:01-12

let arr = [
     {
          name: 'siggaret',
          type: 'tobbako'
     },
     {
          name: 'fanta',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'kent',
          type: 'tobbako'
     },
     {
          name: 'cola',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'sheep',
          type: 'meat'
     }
]

let categories = [
     {
          type: 'vegetables',
          arr: [],
          count: 0
     },
     {
          type: 'tobbako',
          arr: [],
          count: 0
     },
     {
          type: 'liquid',
          arr: [],
          count: 0
     },
     {
          type: 'other',
          arr: [],
          count: 0
     }
]

/*
    
*/


for (let item of arr) {
     for (let category of categories) {
          if(item.type === category.type){
               category.arr.push(item.name)
               category.count  
          } else {
               category.arr.push(item.name)
               category.count  
          }
     }
}

console.log(categories)

There items is not added in others ? What is the problem ?

I try to sort all items by category.

There nested loop is not worked well but I try with for of and there are some problems with sorted.

When I try to sort by item.name and category.type all items' name is added to the all category.

I have two arrays and I need to find the difference between the two and display them in an unordered list.

I can loop through the master array for a single match but I have no clue how to loop through the master list for more than one key value and do it efficiently.

Below is an excerpt of key values from each array:

CodePudding user response:

Instead of looping through two arrays, you could convert categories into an object, where category type is a key, so you can just use type as key:

let arr = [
     {
          name: 'siggaret',
          type: 'tobbako'
     },
     {
          name: 'fanta',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'kent',
          type: 'tobbako'
     },
     {
          name: 'cola',
          type: 'liquid'
     },
     {
          name: 'potato',
          type: 'vegetables'
     },
     {
          name: 'tvorog',
          type: 'milk'
     },
     {
          name: 'steak',
          type: 'meat'
     },
     {
          name: 'sheep',
          type: 'meat'
     }
]

let categories = {
     'vegetables': {
          arr: [],
          count: 0
     },
     'tobbako': {
          arr: [],
          count: 0
     },
     'liquid': {
          arr: [],
          count: 0
     },
     'other': {
          arr: [],
          count: 0
     }
}


for (let item of arr) {
  //get category object or fallback to "other"
  const category = categories[item.type] || categories.other;
  category.arr.push(item.name)
  category.count  
}

console.log(categories)

// now we can get an array sorted by count of our categories name
const sortedByCount = Object.keys(categories) //get array of types
  .sort((a,b) => categories[b].count - categories[a].count) // sort by count
  .map(type => type   " = "    categories[type].count); // append count

console.log("categories sorted by count", sortedByCount);

//or convert it into array w/sorted names
const categoriesArray = Object.keys(categories) //get array of types
  .map(type => //convert types into objects
  {
    const category = Object.assign({}, categories[type]); //clone object
  //  const category = categories[type]; //don't clone object
    category.type = type;

    category.arr = [...category.arr].sort(); //clone array and sort it
  //  category.arr.sort(); //sort array of names without clonning
    return category;
  })
  .sort((a,b) => b.count - a.count); //sort by count
console.log("categories as array sorted by count w / sorted names", categoriesArray);
.as-console-wrapper{top:0;max-height:unset!important;overflow:auto!important;}

CodePudding user response:

In your code, both branches of the if () { ... } else { ... } run the same code. You should remove the else { ... } branch.

Like this:

for (let item of arr) {
     for (let category of categories) {
          if (item.type === category.type){
               category.arr.push(item.name);
               category.count  ;
          }
     }
}

CodePudding user response:

The problem is in the else statement, basically, you don't need the else statement cause if you see the code they both are identical, in your case you are adding items to categories, So remove the else statement:

for (let item of arr){
   for (let category of categories) {
      if(item.type === category.type){
          category.arr.push(item.name);
           category.count  ;
        }
     }
  }

CodePudding user response:

Good start... The problem is your else statement. What happens is that:

else {
       category.arr.push(item.name)
       category.count  
 }

... triggers to often. Every time a category does not match it is pushed.

Fix: You need handle the "pushing to "others" part" outside of that loop.

CodePudding user response:

You can use a combination of Object.values() and Array#reduce() methods as follows, and then use sort with map to sort the arrays:

const 
    arr = [ { name: 'siggaret', type: 'tobbako' }, { name: 'fanta', type: 'liquid' }, { name: 'potato', type: 'vegetables' }, { name: 'tvorog', type: 'milk' }, { name: 'steak', type: 'meat' }, { name: 'kent', type: 'tobbako' }, { name: 'cola', type: 'liquid' }, { name: 'potato', type: 'vegetables' }, { name: 'tvorog', type: 'milk' }, { name: 'steak', type: 'meat' }, { name: 'sheep', type: 'meat' } ],
    
    categories = Object.values(
        arr.reduce(
            (acc,{name,type}) => 
              ({
                ...acc,[type]:{
                  type,
                  arr:[...(acc[type] && acc[type]?.arr || []),name],
                  count:(acc[type] && acc[type].count || 0)   1
                }
              }), {}
        )
    )
    .sort((a,b) => a.type.localeCompare(b.type))
    .map(({type,arr,count}) => ({type,arr:arr.sort((a,b) => a.localeCompare(b)),count}));
    
    console.log( categories );

  • Related