0

Im looking to flatten the following structure below

    [{
        "intGroup": "France",
        "events": [{
            "title": "test admin event"
        }]
    }, {
        "intGroup": "Hungary",
        "events": [{
            "title": "first instance of a title related to hungary"
        }]
    }, {
        "intGroup": "Hungary",
        "events": [{
            "title": "another test item"
        }]
    }, {
        "intGroup": "Hungary",
        "events": [{
            "title": "third instance of test item"
        }]
    }, {
        "intGroup": "France",
        "events": [{
            "title": "second french item"
        }]
    }]

So that I can aggregate by country and then store the sub events into 1 child array as follows

    [{
        "intGroup": "France",
        "events": [{
            "title": "test admin event"
        }, {
            "title": "second french item"
        }]
    }, {
        "intGroup": "Hungary",
        "events": [{
            "title": "first instance of a title related to hungary"
        }, {
            "title": "another test item"
        }, {
            "title": "third instance of test item"
        }]
    }]

Ideally id like to do this in the most performant way as possible, I was using a very crude method of checking, pushing pulling into arrays but I killed my local Javascript garbage collection system and the result set is not even that large !!

            for (let index = 0; index < groups.length; index++) {
                const element = groups[index];
                    let existsIndex = eventsTmp.findIndex( (item: any) => item.intGroup === element.title && item.intGroup !== undefined )
                    if(  Number(existsIndex) >= 0 ) { // a record exists with this interest group, append to it
                        index = existsIndex
                        eventsTmp[index].events.push(<IEvent>prepareEvt)
                    } 
                    else { // create fresh record
                        eventsIdsTmp.push({ eventID: event_id, intGrp: element.title })
                        eventsTmp.push({ intGroup: element.title, events: [prepareEvt] })
                    }                    
            }
Kravitz
  • 2,769
  • 6
  • 26
  • 53

3 Answers3

3

Create a hash to group them

let data =     [{
    "intGroup": "France",
    "events": [{
        "title": "test admin event"
    }]
}, {
    "intGroup": "Hungary",
    "events": [{
        "title": "first instance of a title related to hungary"
    }]
}, {
    "intGroup": "Hungary",
    "events": [{
        "title": "another test item"
    }]
}, {
    "intGroup": "Hungary",
    "events": [{
        "title": "third instance of test item"
    }]
}, {
    "intGroup": "France",
    "events": [{
        "title": "second french item"
    }]
}];

let grouped = data.reduce((a,c)=>{
  let country = c.intGroup;
  country in a ? a[country].events.push(...c.events) : a[country] = c;
  return a;
},{});
console.log(Object.values(grouped));
TheMaster
  • 45,448
  • 6
  • 62
  • 85
1

Use reduce instead of the for loop :

const arr =   [{
  "intGroup": "France",
  "events": [{
      "title": "test admin event"
  }]
}, {
  "intGroup": "Hungary",
  "events": [{
      "title": "first instance of a title related to hungary"
  }]
}, {
  "intGroup": "Hungary",
  "events": [{
      "title": "another test item"
  }]
}, {
  "intGroup": "Hungary",
  "events": [{
      "title": "third instance of test item"
  }]
}, {
  "intGroup": "France",
  "events": [{
      "title": "second french item"
  }]
}];

const result = arr.reduce((acc, curr) => {
  const ndx = acc.findIndex(e => e.intGroup === curr.intGroup);
  if(ndx > -1){
    acc[ndx].events.push(...curr.events)
  }
  else{
    acc.push(curr)
  }
  return acc;
}, [])

console.log(result)
Taki
  • 17,320
  • 4
  • 26
  • 47
0

While you was asking about a very performant version, you could take a for ... of syntax and use a hash table for keeping the same object reference, as well as pushing the same object in insertation order to the result set.

var data = [{ intGroup: "France", events: [{ title: "test admin event" }] }, { intGroup: "Hungary", events: [{ title: "first instance of a title related to hungary" }] }, { intGroup: "Hungary", events: [{ title: "another test item" }] }, { intGroup: "Hungary", events: [{ title: "third instance of test item" }] }, { intGroup: "France", events: [{ title: "second french item" }] }],
    grouped = [],
    hash = {},
    object;

for (object of data) {
    if (!hash[object.intGroup]) grouped.push(hash[object.intGroup] = { ...object, events: [] });
    hash[object.intGroup].events.push(...object.events);
}

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392