1

I am trying to learn more about array of objects. I have flatten array of objects and i am trying to nest it with levels when they have unique values. The thing is now i am using reduce, and getting new objects for each.

data = [
{ name1 : 'Tenis', id1: 1, name2: ATP, id2: 2, name3: Men Singles, id3: 4}
{ name1 : 'Tenis', id1: 1, name2: ATP, id2: 2, name3: Men Singles, id3: 4}
{ name1 : 'Tenis', id1: 1, name2: ATP, id2: 2, name3: Men Doubles, id3: 5}
{ name1 : 'Tenis', id1: 1, name2: WTA, id2: 3, name3: Women Doubles, id3: 6}
{ name1 : 'Tenis', id1: 1, name2: WTA, id2: 3, name3: Women Singles, id3: 7}
]

I want result to be:

result: [
 { sport: 'Tenis', 
   league: 
      [{ 
       ATP: [{ event: Men Singles, Men Doubles }]
       WTA: [{ event: Women Singles, Women Doubles   }]
      }]
}]

My code now:

const result = data.reduce((arr, item) => {
        if (arr.indexOf(item.name1) === -1) {
          arr.push({
            sport: item.name1 ,
            league: item.name2 ,
            event: item.name3 ,
          })
        }
        return arr
      }, [])

But i am getting every value:

0: {sportName: 'Tenis', league: 'ATP', event: 'Men Singles'}
1: {sportName: 'Tenis', league: 'WTA', event: 'Women Doubles'}
2: {sportName: 'Tenis', league: 'WTA', event: 'Women Doubles'}
.... etc

What i need to do, to obtain one nested object? I am literally blocked in mind.

Arssin
  • 23
  • 5
  • Does this answer your question? [How can I group an array of objects by key?](https://stackoverflow.com/questions/40774697/how-can-i-group-an-array-of-objects-by-key) – IT goldman Jul 30 '22 at 17:06
  • Why you always need to wrap object in array? – A1exandr Belan Jul 30 '22 at 19:48
  • @A1exandrBelan i literally thought that will be the best practice, but now i see it's looking very bad and should nest it in another way :< Still learning – Arssin Jul 30 '22 at 20:15

2 Answers2

1

You need to push to the specific inner arrays after checking if the value is already in there. We do this for the sport, then the league, then the event.

Note: I used an array for the events property.

data = [
{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Singles', id3: 4},
{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Singles', id3: 4},
{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Doubles', id3: 5},
{ name1 : 'Tenis', id1: 1, name2: 'WTA', id2: 3, name3: 'Women Doubles', id3: 6},
{ name1 : 'Tenis', id1: 1, name2: 'WTA', id2: 3, name3: 'Women Singles', id3: 7}
]


const result = data.reduce((output, obj) => {
  // Sport Check - if not in, add the sport with the current league & event
  const sportObj = output.find(item => item.sport === obj.name1)
  if (!sportObj) {
    output.push( 
      { 
        sport: obj.name1,
        league: [{
          [obj.name2]: [{ events: [obj.name3] }]
         }] 
       })
    return output
  }
  // League Check - If not in, add a league to the sport with the current event
  const leagueObj = sportObj.league[0][obj.name2]
  if (!leagueObj) {
    sportObj.league[0][obj.name2] = [{ events: [obj.name3] }]
  } else {
    // Event Check - if not in, add the event. If not, don't do anything.
    const eventsArray = leagueObj[0].events
    if (!eventsArray.includes(obj.name3)) eventsArray.push(obj.name3)
  }
  return output
}, [])
 
 console.log(result)
Brother58697
  • 2,290
  • 2
  • 4
  • 12
  • Thanks, very good response tho... after seeing this i think i made a bit of overthinking and should not nest everything in objects, maybe just [Tenis: [ATP[events], WTA[events]. Still very good lesson for me really thanks – Arssin Jul 30 '22 at 20:19
1

I definitely recommend not wrapping each object with an array

const data = [{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Singles', id3: 4},{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Singles', id3: 4},{ name1 : 'Tenis', id1: 1, name2: 'ATP', id2: 2, name3: 'Men Doubles', id3: 5},{ name1 : 'Tenis', id1: 1, name2: 'WTA', id2: 3, name3: 'Women Doubles', id3: 6},{ name1 : 'Tenis', id1: 1, name2: 'WTA', id2: 3, name3: 'Women Singles', id3: 7}]

const tranform = () => {
  const sport = data[0]['name1'];
  const league = data.reduce((r, e) => {
      r[e['name2']] ??= []
      if (!r[e['name2']].includes(e['name3'])) {                
        r[e['name2']].push(e['name3'])
      }
      return r;
  }, {});

  return { sport, league };
};
  
console.log(tranform())
.as-console-wrapper { max-height: 100% !important; top: 0 }
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48
  • For sure! :) Thanks once again – Arssin Jul 30 '22 at 20:46
  • If i can one more question, to add another nesting level in the future(to the name3) do i need to make again data.reduce or it is possible to done it at league? – Arssin Jul 30 '22 at 21:27
  • @Arssin, yes its possible but implementation depends on result you need. Just post new question and somebody helps you – A1exandr Belan Jul 31 '22 at 03:44