0

I am trying to take single denominational array and group the items in a multi-denominational array.

Here is what I did

$(function(){
    
 // this array should be groupped by group value "if one exists." In this case, it should be 2 groups
 // (group_1 and group_2)
    var items = [
        {
            group: "group_1",
            text: "Text 1",
            value: "1",
        },      
        {
            group: "group_2",
            text: "Text 1",
            value: "21",
        },
        {
            group: "group_1",
            text: "Text 2",
            value: "2",
        },
        {
            group: "group_1",
            text: "Text 3",
            value: "3",
        },
        {
            text: "Text 30",
            value: "30",
        }
    ];


    var groups = [];

    $.each(items, function(i, item){

        if( typeof item.group === 'undefined'){
            return; // continue, ignore any item that does not have a group name
        }
    
    if( !(item.group in groups)) {
          // create a new group in the array
            groups[item.group] = [];
    }
        // push item to the group
        groups[item.group].push({text: item.text, value: item.value});

    });

    $('#console').text('Expecting the length to be 2 groups but getting ' + groups.length);
  console.log(groups);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="console">
</div>

I am expecting the length of the groups array to be 2 since there is group_1 and group_2. However, I am getting array with 0 length.

How can I correctly group these items by the value of the group property?

1
  • 1
    The main issue with your current attempt is that you use an array (groups = []) while using "group_1" to access each group. Those are not indexes, but keys. Using an object would solve the majority of the problem. This means replacing groups = [] with groups = {}. (keep in mind an object does not have a length property.) Commented Dec 1, 2020 at 17:41

1 Answer 1

0

something like that ?

see Array.prototype.reduce()

const items = 
  [ { group: "group_1", text: "Text 1",  value: "1"  } 
  , { group: "group_2", text: "Text 1",  value: "21" } 
  , { group: "group_1", text: "Text 2",  value: "2"  } 
  , { group: "group_1", text: "Text 3",  value: "3"  } 
  , {                   text: "Text 30", value: "30" } 
  ] 

const groups = items.reduce((r,{group,...other})=>
  {
  if (!group) return r
  let grp = r.find(x=>x.some(z=>z.group===group))
  if (!grp) r.push([{group,...other}])
  else grp.push( {group,...other} )
  return r
  }
  ,[])

console.log( groups ) 

Or:

const items = 
  [ { group: "group_1", text: "Text 1",  value: "1"  } 
  , { group: "group_2", text: "Text 1",  value: "21" } 
  , { group: "group_1", text: "Text 2",  value: "2"  } 
  , { group: "group_1", text: "Text 3",  value: "3"  } 
  , {                   text: "Text 30", value: "30" } 
  ] 
       
const groups = items.reduce((r, { group, ...other})=>
  {
  if (!group) return r
  let grp = r.find(x=>x.group===group)
  if (!grp) 
    {
    grp = { group, elements:[] }
    r.push(grp)
    }
  grp.elements.push({...other})
  return r
  }
  ,[]);

console.log(  groups )

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.