Home > Software design >  Grouping an array of object by a keyword in key
Grouping an array of object by a keyword in key

Time:03-26

I have an array of objects as follows

const data =   [
   {
      "id": 66,
      "Time": "2022-03-24 05:58:59",
      "Data": "1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 2 2 2",
   },
   {
      "id": 57,
      "Time": "2022-03-24 02:58:01",
      "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
     "id": 65,
      "Time": "2022-03-23 23:58:01",
       "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
     "id": 59,
      "Time": "2022-03-23 21:59:01",
       "Data": "39 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2",
      },
    {
      "id": 42,
      "Time": "2022-03-23 06:35:20",
      "Data": "1 1 1 1 1 1 1 1 1 1 1 1 2 2",
   },
   {
      "id": 48,
      "Time": "2022-03-23 01:58:01",
      "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
     "id": 35,
      "Time": "2022-03-22 23:58:01",
       "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
     "id": 59,
      "Time": "2022-03-22 20:59:01",
       "Data": "39 2 2 2 1 1 1 2 2",
      },
      ....................

So, the number 39 indicates that the data retrieval has started and it will be continue for some hours and then it will stop. When we see next 39, then it indicates that the process has stopped earlier. So we need to group the data when number 39 is listed until next 39. I am trying to group the data by separating the key in the data key. So I am trying to use 39 to separate the data and group that in this format. This is the output

const data = 
   {
    "1": [
        {
      "id": 66,
      "Time": "2022-03-24 05:58:59",
      "Data": "1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 2 2 2",
   },
   {
      "id": 57,
      "Time": "2022-03-24 02:58:01",
      "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
     "id": 65,
      "Time": "2022-03-23 23:58:01",
       "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
     "id": 59,
      "Time": "2022-03-23 21:59:01",
       "Data": "39 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2",
      },
    ]
    "2": [ {
      "id": 42,
      "Time": "2022-03-23 06:35:20",
      "Data": "1 1 1 1 1 1 1 1 1 1 1 1 2 2",
   },
   {
      "id": 48,
      "Time": "2022-03-23 01:58:01",
      "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
     "id": 35,
      "Time": "2022-03-22 23:58:01",
       "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
     "id": 59,
      "Time": "2022-03-22 20:59:01",
       "Data": "39 2 2 2 1 1 1 2 2",
      }]
     ..........

I used lodash groupby to separate the data but not been able to grab the data. This is what I did

   const grouped =_.groupBy(data, item => item.Data.split('39').length-1);

Any idea will be greatful

CodePudding user response:

Maybe you will change rule frequency,so i suggest you make rule as "callback function" to control your id

function Groupz(arr=[],idcondition=(a,b)=>b){
    var l=arr.length;
    var obj_rs={};
    for(var i=0,j=1;i<l;i  ){
        if(!(j in obj_rs)){
            obj_rs[j]=[];
        }
        obj_rs[j].push(arr[i]);
        j=idcondition(arr[i].Data,j)
    }
    return obj_rs;
}
var data=   [
   {
  "id": 66,
  "Time": "2022-03-24 05:58:59",
  "Data": "1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 2 2 2",
   },
   {
  "id": 57,
  "Time": "2022-03-24 02:58:01",
  "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
 "id": 65,
  "Time": "2022-03-23 23:58:01",
   "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
 "id": 59,
  "Time": "2022-03-23 21:59:01",
   "Data": "39 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2",
  },
{
  "id": 42,
  "Time": "2022-03-23 06:35:20",
  "Data": "1 1 1 1 1 1 1 1 1 1 1 1 2 2",
   },
   {
  "id": 48,
  "Time": "2022-03-23 01:58:01",
  "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
  },
  {
 "id": 35,
  "Time": "2022-03-22 23:58:01",
   "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
   },
   {
 "id": 59,
  "Time": "2022-03-22 20:59:01",
   "Data": "39 2 2 2 1 1 1 2 2",
  },]
var final_group=Groupz(data,function(a,b){
    //Remove mutiple space,reduce to 1 space then split by single space
    var numbers=a.replace(/  (?= )/g,'').split(' ');
    var l=numbers.length;
    /*
    //If you want check all number using this to loop all numbers to check whether 39 in string not only check first place
    for(var i=0;i<l;i  ){
        if(numbers[i]=="39"){
            return b 1;
        }
    }
    
    return b;*/
    return b !!(numbers.length>1&&numbers[0]=="39");
})

console.log(final_group);

CodePudding user response:

The groubBy function expects a key OR a function returning a key, to know where to put a given element. What you did is to put all elements who did have a 39 within one group and all elements not containing any 39 in another group.

Grouping the data using groupBy

const data = [
    {
        "id": 66,
        "Time": "2022-03-24 05:58:59",
        "Data": "1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 2 2 2 2",
    },
    {
        "id": 57,
        "Time": "2022-03-24 02:58:01",
        "Data": "2 3 1 1 1 3 1 1 1 1 1 1 1 11",
    },
    {
        "id": 65,
        "Time": "2022-03-23 23:58:01",
        "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
    },
    {
        "id": 59,
        "Time": "2022-03-23 21:59:01",
        "Data": "39 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2",
    },
    {
        "id": 42,
        "Time": "2022-03-23 06:35:20",
        "Data": "1 1 1 1 1 1 1 1 1 1 1 1 2 2",
    },
    {
        "id": 48,
        "Time": "2022-03-23 01:58:01",
        "Data": "39 3 1 1 1 3 1 1 1 1 1 1 1 11",
    },
    {
        "id": 35,
        "Time": "2022-03-22 23:58:01",
        "Data": "1 3 1 1 1 1 1 2 1 1 1 1 1",
    }

]

// keep track of the group. 
let groupKey = 0

const grouped = groupBy(data, element => {

    // increment the group as one element is found.
    if (element.Data.indexOf('39') > -1) {
        groupKey  
    }

    return groupKey 
})

console.log(grouped)

Object.keys(grouped).forEach(k => {
    console.log('group key:', k, 'element count:', grouped[k].length)
})


Note if the first element contains a 39 the resulting groups will start with 1 and else with 0. So make sure the first element will always hold 39 OR make sure it will always not hold 39. Ensure that it is consistent.

Feel free to leave a comment if you have any questions.

  • Related