0

i having trouble to transform the following array data1 to look like data2:I tried to use lodash but its a bit strange _gropuby gives me an object array. Should i be looping inside the array...creating a custom function for this. or is there a trick in lodash to simplify this. Thankssss /********************************************************************************************

let data1 = [{
    KlasCode: "AA",
    LESDatum: "06/02/2017",
    LESID: "1",
    ModuleID: "1061",
    ParticipationLetterCode: "Y"
  }, {
    KlasCode: "AA",
    LESDatum: "07/02/2017",
    LESID: "2",
    ModuleID: "1061",
    ParticipationLetterCode: "X",
  },
  {
    KlasCode: "AA",
    LESDatum: "13/02/2017",
    LESID: "3",
    ModuleID: "1062",
    ParticipationLetterCode: "Z"
  },
  {
    KlasCode: "BB",
    LESDatum: "16/02/2017",
    LESID: "4",
    ModuleID: "1063",
    ParticipationLetterCode: "X"
  }
]

//The output should be like a tree array system, something more organized such as the following code :
let data2 = [{
    KlasCode: "AA",
    Modules: [
      {
      ModuleID: "1061",
      Participation: [{
          ParticipationLetterCode: "Y",
          LESDatum: "06/02/2017",
          LESID: "1"
        },
        {
          ParticipationLetterCode: "X",
          LESDatum: "07/02/2017",
          LESID: "2"
        }
      },
       {
          ModuleID: "1062",
          Participation:[{
          ParticipationLetterCode: "Z",
          LESDatum: "13/02/2017",
          LESID: "3"
                         }]
        }

    }]
  },
  {
    KlasCode: "BB",
    Modules: [{
      ModuleID: "1063",
      Participation: [{
        ParticipationLetterCode: "x",
        LESDatum: "6/02/2017",
        LESID: "4"
      }]

    }]
  }

]

2
  • supposed to be AA sorry, i updated the thing thx.I tried to combine .map() and _gropuby. no luck Commented May 4, 2020 at 14:23
  • does that help ? Commented May 4, 2020 at 14:27

3 Answers 3

2

Created a function to do the same, hope this helps -:

const custommodifier = (data) => Object.values(data.reduce((acc,{KlasCode, ModuleID, ...participationData}) => {
    if(acc[KlasCode]){
        acc[KlasCode].Modules[0].Participation.push({
            ...participationData
        })
    }
    else {
        acc[KlasCode] = {
            KlasCode,
            Modules: [{
                ModuleID,
                Participation: [{
                    ...participationData
                }]
            }]
        }
    }
    return acc;
}, {}));


let data = [{
    KlasCode: "AA",
    LESDatum: "06/02/2017",
    LESID: "1",
    ModuleID: "1061",
    ParticipationLetterCode: "Y"
  }, {
    KlasCode: "AA",
    LESDatum: "07/02/2017",
    LESID: "2",
    ModuleID: "1061",
    ParticipationLetterCode: "X",
  },
  {
    KlasCode: "AA",
    LESDatum: "13/02/2017",
    LESID: "3",
    ModuleID: "1061",
    ParticipationLetterCode: "Z"
  },
  {
    KlasCode: "BB",
    LESDatum: "16/02/2017",
    LESID: "4",
    ModuleID: "1062",
    ParticipationLetterCode: "X"
  }
]
console.log(custommodifier(data))

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

1 Comment

Abhisar, I been trying to use this reduce funciotn for a similar thread:can you help me checking it out?:stackoverflow.com/q/61610032/9248040 thx
1

You could take a dynamic approach with an array of keys ad group names and take the keys out of the actual object. At the end, after building nested groups, add the final object to the last group.

This approach works for more nested groups if necessary.

let data = [{ KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y" }, { KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X" }, { KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1061", ParticipationLetterCode: "Z" }, { KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1062", ParticipationLetterCode: "X" }],
    groups = [['KlasCode', 'Modules'], ['ModuleID', 'Participation']],
    result = data.reduce((r, o) => {
        groups
            .reduce((p, [key, group]) => {
                let value, temp;
                ({ [key]: value, ...o } = o);
                temp = p.find(q => q[key] === value);
                if (!temp) p.push(temp = { [key]: value, [group]: [] });
                return temp[group];
            }, r)
            .push(o);
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

1

I would use a groupBy function in conjunction with a little fiddling with Object.entries. You will need to use it twice, to handle your two levels of grouping.

You could use the groupBy from lodash (or the one from Ramda, or wherever), or the simple one included here.

const groupBy = (fn) => (xs) => 
  xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})

const transform = (data) => Object.entries (groupBy (x => x.KlasCode) (data))
  .map(([KlasCode, Modules]) => ({
    KlasCode, 
    Modules: Object.entries(groupBy (x => x.ModuleID) (Modules))
      .map(([ModuleID, Participations]) => ({
        ModuleID,
        Participation: Participations.map (({ParticipationLetterCode, KlasCode, ...rest}) => rest)
      })
    )
  }))

let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]

console .log (transform (data1))
.as-console-wrapper {min-height: 100% !important; top: 0}

Update -- a Ramda alternative

I wasn't thrilled by the above solution, nor by the other answers here. Sometimes when that happens, I rewrite in Ramda (disclaimer: I'm one of its authors) and then port the Ramda functions involved into vanilla JS. I'm not going to do the latter this time, but I will share how I might do this taking advantage of a library like Ramda. I'm guessing that there are similar features in lodash.

const groupByProp = (propName, childName) => pipe (
  groupBy (prop (propName)),
  toPairs,
  map (evolve ([ , map (dissoc (propName))])),
  map (zipObj ([propName, childName]))
)

const transform = pipe (
  groupByProp('KlasCode', 'Modules'),
  map (evolve ({Modules: groupByProp('ModuleID', 'Participation')}))
)

let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]

console .log (transform (data1))
.as-console-wrapper {min-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {groupBy, prop, toPairs, map, evolve, dissoc, zipObj, pipe} = R </script>

I feel as though these functions are simpler and better show the steps of the transformation. But this is not enough of a reason to include a library. But once you have a few such situations, a library seems to make a great deal of sense.

I'm not trying to push Ramda here, just to point out that when you have the tools of a utility library at your disposal, you can often write simpler code.

2 Comments

Thanks you Scott for the advice.
can you help me with this simalar thread?:stackoverflow.com/q/61610032/9248040

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.