Using lodash.groupBy() to normalise objects












0















I have a denormalized array of three different objects - country, school, student



const input= 
[
{
countryID: 12,
country: "US",
schoolID: 122,
schoolZone: "Highlands",
studentID: 142,
studentName: "Mary"
},
{
countryID: 12,
country: "US",
schoolID: 122,
schoolZone: "Highlands",
studentID: 145,
studentName: "John"
},
{
countryID: 14,
country: "UK",
schoolID: 222,
schoolZone: "Leeds",
studentID: 223,
studentName: "Peter"
}
];


I would like to normalise them like this



const result= 
[
{
countryID: 12,
country: "US",
schools: [
{
schoolID: 122,
schoolZone: "Highlands",
students: [
{
studentID: 142,
studentName: "Mary"
},
{
studentID: 145,
studentName: "John"
}
]
}
]
},
{
countryID: 14,
country: "UK",
schools: [
{
schoolID: 222,
schoolZone: "Leeds",
students: [
{
studentID: 223,
studentName: "Peter"
}
]
}
]
}
];


I understand lodash and ramda can be used to achieve nested normalisation



But I am new to both libraries.



Could you please help me with an implementation ? Also wondering if currying would be a consideration given there is nesting of schools and students










share|improve this question



























    0















    I have a denormalized array of three different objects - country, school, student



    const input= 
    [
    {
    countryID: 12,
    country: "US",
    schoolID: 122,
    schoolZone: "Highlands",
    studentID: 142,
    studentName: "Mary"
    },
    {
    countryID: 12,
    country: "US",
    schoolID: 122,
    schoolZone: "Highlands",
    studentID: 145,
    studentName: "John"
    },
    {
    countryID: 14,
    country: "UK",
    schoolID: 222,
    schoolZone: "Leeds",
    studentID: 223,
    studentName: "Peter"
    }
    ];


    I would like to normalise them like this



    const result= 
    [
    {
    countryID: 12,
    country: "US",
    schools: [
    {
    schoolID: 122,
    schoolZone: "Highlands",
    students: [
    {
    studentID: 142,
    studentName: "Mary"
    },
    {
    studentID: 145,
    studentName: "John"
    }
    ]
    }
    ]
    },
    {
    countryID: 14,
    country: "UK",
    schools: [
    {
    schoolID: 222,
    schoolZone: "Leeds",
    students: [
    {
    studentID: 223,
    studentName: "Peter"
    }
    ]
    }
    ]
    }
    ];


    I understand lodash and ramda can be used to achieve nested normalisation



    But I am new to both libraries.



    Could you please help me with an implementation ? Also wondering if currying would be a consideration given there is nesting of schools and students










    share|improve this question

























      0












      0








      0








      I have a denormalized array of three different objects - country, school, student



      const input= 
      [
      {
      countryID: 12,
      country: "US",
      schoolID: 122,
      schoolZone: "Highlands",
      studentID: 142,
      studentName: "Mary"
      },
      {
      countryID: 12,
      country: "US",
      schoolID: 122,
      schoolZone: "Highlands",
      studentID: 145,
      studentName: "John"
      },
      {
      countryID: 14,
      country: "UK",
      schoolID: 222,
      schoolZone: "Leeds",
      studentID: 223,
      studentName: "Peter"
      }
      ];


      I would like to normalise them like this



      const result= 
      [
      {
      countryID: 12,
      country: "US",
      schools: [
      {
      schoolID: 122,
      schoolZone: "Highlands",
      students: [
      {
      studentID: 142,
      studentName: "Mary"
      },
      {
      studentID: 145,
      studentName: "John"
      }
      ]
      }
      ]
      },
      {
      countryID: 14,
      country: "UK",
      schools: [
      {
      schoolID: 222,
      schoolZone: "Leeds",
      students: [
      {
      studentID: 223,
      studentName: "Peter"
      }
      ]
      }
      ]
      }
      ];


      I understand lodash and ramda can be used to achieve nested normalisation



      But I am new to both libraries.



      Could you please help me with an implementation ? Also wondering if currying would be a consideration given there is nesting of schools and students










      share|improve this question














      I have a denormalized array of three different objects - country, school, student



      const input= 
      [
      {
      countryID: 12,
      country: "US",
      schoolID: 122,
      schoolZone: "Highlands",
      studentID: 142,
      studentName: "Mary"
      },
      {
      countryID: 12,
      country: "US",
      schoolID: 122,
      schoolZone: "Highlands",
      studentID: 145,
      studentName: "John"
      },
      {
      countryID: 14,
      country: "UK",
      schoolID: 222,
      schoolZone: "Leeds",
      studentID: 223,
      studentName: "Peter"
      }
      ];


      I would like to normalise them like this



      const result= 
      [
      {
      countryID: 12,
      country: "US",
      schools: [
      {
      schoolID: 122,
      schoolZone: "Highlands",
      students: [
      {
      studentID: 142,
      studentName: "Mary"
      },
      {
      studentID: 145,
      studentName: "John"
      }
      ]
      }
      ]
      },
      {
      countryID: 14,
      country: "UK",
      schools: [
      {
      schoolID: 222,
      schoolZone: "Leeds",
      students: [
      {
      studentID: 223,
      studentName: "Peter"
      }
      ]
      }
      ]
      }
      ];


      I understand lodash and ramda can be used to achieve nested normalisation



      But I am new to both libraries.



      Could you please help me with an implementation ? Also wondering if currying would be a consideration given there is nesting of schools and students







      javascript lodash ramda.js






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 24 '18 at 11:39









      Theepan ThevathasasnTheepan Thevathasasn

      5819




      5819
























          3 Answers
          3






          active

          oldest

          votes


















          1














          A way without using lodash or ramda could be this. Hope this helps.






          const input= [{
          countryID: 12,
          country: "US",
          schoolID: 122,
          schoolZone: "Highlands",
          studentID: 142,
          studentName: "Mary"
          }, {
          countryID: 12,
          country: "US",
          schoolID: 122,
          schoolZone: "Highlands",
          studentID: 145,
          studentName: "John"
          }, {
          countryID: 14,
          country: "UK",
          schoolID: 222,
          schoolZone: "Leeds",
          studentID: 223,
          studentName: "Peter"
          }];

          const normalize = (data) =>

          data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

          const studentToAdd = { studentID, studentName };

          const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

          const countryToAdd = { countryID, country, schools: [schoolToAdd] };

          const existingCountry = acc.find(item => item.countryID === countryID);

          if (existingCountry) {

          const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

          if (existingSchool) {

          const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

          if (!existingStudent) existingSchool.students.push(studentToAdd);
          }

          else existingCountry.schools.push(schoolToAdd);
          }

          else acc.push(countryToAdd);

          return acc;
          }, );

          console.log(normalize(input));








          share|improve this answer































            1














            With lodash you can solve this in the following concise way:






            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

            const grp = (arr, key, field, group, o=0) => _(arr)
            .groupBy(key)
            .mapValues(x => ({
            [key]: _.head(x)[key],
            [field]: _.head(x)[field],
            [group]: o
            ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
            }))
            .values()
            .value()
            console.log(grp(data, 'countryID', 'country', 'schools'))

            <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





            The idea is to use recursive approach where you call the same grouping function 2 times. Inside of which we would _.groupBy and just do _.mapValues



            Now the exact same idea with compact ES6 code would look like:






            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

            const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
            const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

            const grp = (arr, k, f, b, o=0) =>
            Object.values(Object.values(groupBy(arr, k)).map(x => ({
            [k]: x[0][k],
            [f]: x[0][f],
            [b]: o
            ? x.map(s => pick(s, ['studentID', 'studentName']))
            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
            })))

            console.log(grp(data, 'countryID', 'country', 'schools'))








            share|improve this answer

































              0














              First reshape each object to look like the final data structure:



              reshape({
              countryID: 12,
              country: "US",
              schoolID: 122,
              schoolZone: "Highlands",
              studentID: 142,
              studentName: "Mary" });

              //=> {
              //=> country: "US",
              //=> countryID: 12,
              //=> schools: [
              //=> {
              //=> schoolID: 122,
              //=> schoolZone: "Highlands",
              //=> students: [
              //=> {
              //=> studentID: 142,
              //=> studentName: "Mary"
              //=> }
              //=> ]
              //=> }
              //=> ]
              //=> }


              Then it is simply a matter of grouping by countries then by schools and using a map & reduce function to merge objects.






              const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

              const input = [
              { countryID: 12,
              country: "US",
              schoolID: 122,
              schoolZone: "Highlands",
              studentID: 142,
              studentName: "Mary" },

              { countryID: 12,
              country: "US",
              schoolID: 122,
              schoolZone: "Highlands",
              studentID: 145,
              studentName: "John" },

              { countryID: 14,
              country: "UK",
              schoolID: 222,
              schoolZone: "Leeds",
              studentID: 223,
              studentName: "Peter" }];

              const reshape = applySpec({
              countryID: prop('countryID'),
              country: prop('country'),
              schools: converge(
              pipe(set(lensProp('students')), of), [
              pipe(pick(['studentID', 'studentName']), of),
              pick(['schoolID', 'schoolZone'])])
              });

              const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

              const groupStudents = pipe(
              groupBy(prop('schoolID')),
              values,
              map(reduce(mergeArrays('students'), {})));

              const process = pipe(
              map(reshape),
              groupBy(prop('countryID')),
              map(reduce(mergeArrays('schools'), {})),
              map(over(lensProp('schools'), groupStudents)),
              values);

              console.log(process(input));

              <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>








              share|improve this answer

























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53457733%2fusing-lodash-groupby-to-normalise-objects%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                1














                A way without using lodash or ramda could be this. Hope this helps.






                const input= [{
                countryID: 12,
                country: "US",
                schoolID: 122,
                schoolZone: "Highlands",
                studentID: 142,
                studentName: "Mary"
                }, {
                countryID: 12,
                country: "US",
                schoolID: 122,
                schoolZone: "Highlands",
                studentID: 145,
                studentName: "John"
                }, {
                countryID: 14,
                country: "UK",
                schoolID: 222,
                schoolZone: "Leeds",
                studentID: 223,
                studentName: "Peter"
                }];

                const normalize = (data) =>

                data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                const studentToAdd = { studentID, studentName };

                const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                const existingCountry = acc.find(item => item.countryID === countryID);

                if (existingCountry) {

                const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                if (existingSchool) {

                const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                if (!existingStudent) existingSchool.students.push(studentToAdd);
                }

                else existingCountry.schools.push(schoolToAdd);
                }

                else acc.push(countryToAdd);

                return acc;
                }, );

                console.log(normalize(input));








                share|improve this answer




























                  1














                  A way without using lodash or ramda could be this. Hope this helps.






                  const input= [{
                  countryID: 12,
                  country: "US",
                  schoolID: 122,
                  schoolZone: "Highlands",
                  studentID: 142,
                  studentName: "Mary"
                  }, {
                  countryID: 12,
                  country: "US",
                  schoolID: 122,
                  schoolZone: "Highlands",
                  studentID: 145,
                  studentName: "John"
                  }, {
                  countryID: 14,
                  country: "UK",
                  schoolID: 222,
                  schoolZone: "Leeds",
                  studentID: 223,
                  studentName: "Peter"
                  }];

                  const normalize = (data) =>

                  data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                  const studentToAdd = { studentID, studentName };

                  const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                  const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                  const existingCountry = acc.find(item => item.countryID === countryID);

                  if (existingCountry) {

                  const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                  if (existingSchool) {

                  const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                  if (!existingStudent) existingSchool.students.push(studentToAdd);
                  }

                  else existingCountry.schools.push(schoolToAdd);
                  }

                  else acc.push(countryToAdd);

                  return acc;
                  }, );

                  console.log(normalize(input));








                  share|improve this answer


























                    1












                    1








                    1







                    A way without using lodash or ramda could be this. Hope this helps.






                    const input= [{
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 142,
                    studentName: "Mary"
                    }, {
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 145,
                    studentName: "John"
                    }, {
                    countryID: 14,
                    country: "UK",
                    schoolID: 222,
                    schoolZone: "Leeds",
                    studentID: 223,
                    studentName: "Peter"
                    }];

                    const normalize = (data) =>

                    data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                    const studentToAdd = { studentID, studentName };

                    const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                    const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                    const existingCountry = acc.find(item => item.countryID === countryID);

                    if (existingCountry) {

                    const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                    if (existingSchool) {

                    const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                    if (!existingStudent) existingSchool.students.push(studentToAdd);
                    }

                    else existingCountry.schools.push(schoolToAdd);
                    }

                    else acc.push(countryToAdd);

                    return acc;
                    }, );

                    console.log(normalize(input));








                    share|improve this answer













                    A way without using lodash or ramda could be this. Hope this helps.






                    const input= [{
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 142,
                    studentName: "Mary"
                    }, {
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 145,
                    studentName: "John"
                    }, {
                    countryID: 14,
                    country: "UK",
                    schoolID: 222,
                    schoolZone: "Leeds",
                    studentID: 223,
                    studentName: "Peter"
                    }];

                    const normalize = (data) =>

                    data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                    const studentToAdd = { studentID, studentName };

                    const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                    const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                    const existingCountry = acc.find(item => item.countryID === countryID);

                    if (existingCountry) {

                    const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                    if (existingSchool) {

                    const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                    if (!existingStudent) existingSchool.students.push(studentToAdd);
                    }

                    else existingCountry.schools.push(schoolToAdd);
                    }

                    else acc.push(countryToAdd);

                    return acc;
                    }, );

                    console.log(normalize(input));








                    const input= [{
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 142,
                    studentName: "Mary"
                    }, {
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 145,
                    studentName: "John"
                    }, {
                    countryID: 14,
                    country: "UK",
                    schoolID: 222,
                    schoolZone: "Leeds",
                    studentID: 223,
                    studentName: "Peter"
                    }];

                    const normalize = (data) =>

                    data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                    const studentToAdd = { studentID, studentName };

                    const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                    const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                    const existingCountry = acc.find(item => item.countryID === countryID);

                    if (existingCountry) {

                    const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                    if (existingSchool) {

                    const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                    if (!existingStudent) existingSchool.students.push(studentToAdd);
                    }

                    else existingCountry.schools.push(schoolToAdd);
                    }

                    else acc.push(countryToAdd);

                    return acc;
                    }, );

                    console.log(normalize(input));





                    const input= [{
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 142,
                    studentName: "Mary"
                    }, {
                    countryID: 12,
                    country: "US",
                    schoolID: 122,
                    schoolZone: "Highlands",
                    studentID: 145,
                    studentName: "John"
                    }, {
                    countryID: 14,
                    country: "UK",
                    schoolID: 222,
                    schoolZone: "Leeds",
                    studentID: 223,
                    studentName: "Peter"
                    }];

                    const normalize = (data) =>

                    data.reduce((acc, { studentID, studentName, schoolID, schoolZone, countryID, country }) => {

                    const studentToAdd = { studentID, studentName };

                    const schoolToAdd = { schoolID, schoolZone, students: [studentToAdd] };

                    const countryToAdd = { countryID, country, schools: [schoolToAdd] };

                    const existingCountry = acc.find(item => item.countryID === countryID);

                    if (existingCountry) {

                    const existingSchool = existingCountry.schools.find(item => item.schoolID === schoolID);

                    if (existingSchool) {

                    const existingStudent = existingSchool.students.find(item => item.studentID === studentID);

                    if (!existingStudent) existingSchool.students.push(studentToAdd);
                    }

                    else existingCountry.schools.push(schoolToAdd);
                    }

                    else acc.push(countryToAdd);

                    return acc;
                    }, );

                    console.log(normalize(input));






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 24 '18 at 15:09









                    Alex GAlex G

                    1,221139




                    1,221139

























                        1














                        With lodash you can solve this in the following concise way:






                        const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                        const grp = (arr, key, field, group, o=0) => _(arr)
                        .groupBy(key)
                        .mapValues(x => ({
                        [key]: _.head(x)[key],
                        [field]: _.head(x)[field],
                        [group]: o
                        ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                        : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                        }))
                        .values()
                        .value()
                        console.log(grp(data, 'countryID', 'country', 'schools'))

                        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                        The idea is to use recursive approach where you call the same grouping function 2 times. Inside of which we would _.groupBy and just do _.mapValues



                        Now the exact same idea with compact ES6 code would look like:






                        const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                        const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                        const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                        const grp = (arr, k, f, b, o=0) =>
                        Object.values(Object.values(groupBy(arr, k)).map(x => ({
                        [k]: x[0][k],
                        [f]: x[0][f],
                        [b]: o
                        ? x.map(s => pick(s, ['studentID', 'studentName']))
                        : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                        })))

                        console.log(grp(data, 'countryID', 'country', 'schools'))








                        share|improve this answer






























                          1














                          With lodash you can solve this in the following concise way:






                          const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                          const grp = (arr, key, field, group, o=0) => _(arr)
                          .groupBy(key)
                          .mapValues(x => ({
                          [key]: _.head(x)[key],
                          [field]: _.head(x)[field],
                          [group]: o
                          ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                          : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                          }))
                          .values()
                          .value()
                          console.log(grp(data, 'countryID', 'country', 'schools'))

                          <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                          The idea is to use recursive approach where you call the same grouping function 2 times. Inside of which we would _.groupBy and just do _.mapValues



                          Now the exact same idea with compact ES6 code would look like:






                          const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                          const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                          const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                          const grp = (arr, k, f, b, o=0) =>
                          Object.values(Object.values(groupBy(arr, k)).map(x => ({
                          [k]: x[0][k],
                          [f]: x[0][f],
                          [b]: o
                          ? x.map(s => pick(s, ['studentID', 'studentName']))
                          : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                          })))

                          console.log(grp(data, 'countryID', 'country', 'schools'))








                          share|improve this answer




























                            1












                            1








                            1







                            With lodash you can solve this in the following concise way:






                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const grp = (arr, key, field, group, o=0) => _(arr)
                            .groupBy(key)
                            .mapValues(x => ({
                            [key]: _.head(x)[key],
                            [field]: _.head(x)[field],
                            [group]: o
                            ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            }))
                            .values()
                            .value()
                            console.log(grp(data, 'countryID', 'country', 'schools'))

                            <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                            The idea is to use recursive approach where you call the same grouping function 2 times. Inside of which we would _.groupBy and just do _.mapValues



                            Now the exact same idea with compact ES6 code would look like:






                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                            const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                            const grp = (arr, k, f, b, o=0) =>
                            Object.values(Object.values(groupBy(arr, k)).map(x => ({
                            [k]: x[0][k],
                            [f]: x[0][f],
                            [b]: o
                            ? x.map(s => pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            })))

                            console.log(grp(data, 'countryID', 'country', 'schools'))








                            share|improve this answer















                            With lodash you can solve this in the following concise way:






                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const grp = (arr, key, field, group, o=0) => _(arr)
                            .groupBy(key)
                            .mapValues(x => ({
                            [key]: _.head(x)[key],
                            [field]: _.head(x)[field],
                            [group]: o
                            ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            }))
                            .values()
                            .value()
                            console.log(grp(data, 'countryID', 'country', 'schools'))

                            <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                            The idea is to use recursive approach where you call the same grouping function 2 times. Inside of which we would _.groupBy and just do _.mapValues



                            Now the exact same idea with compact ES6 code would look like:






                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                            const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                            const grp = (arr, k, f, b, o=0) =>
                            Object.values(Object.values(groupBy(arr, k)).map(x => ({
                            [k]: x[0][k],
                            [f]: x[0][f],
                            [b]: o
                            ? x.map(s => pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            })))

                            console.log(grp(data, 'countryID', 'country', 'schools'))








                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const grp = (arr, key, field, group, o=0) => _(arr)
                            .groupBy(key)
                            .mapValues(x => ({
                            [key]: _.head(x)[key],
                            [field]: _.head(x)[field],
                            [group]: o
                            ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            }))
                            .values()
                            .value()
                            console.log(grp(data, 'countryID', 'country', 'schools'))

                            <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const grp = (arr, key, field, group, o=0) => _(arr)
                            .groupBy(key)
                            .mapValues(x => ({
                            [key]: _.head(x)[key],
                            [field]: _.head(x)[field],
                            [group]: o
                            ? _.map(x, s => _.pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            }))
                            .values()
                            .value()
                            console.log(grp(data, 'countryID', 'country', 'schools'))

                            <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>





                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                            const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                            const grp = (arr, k, f, b, o=0) =>
                            Object.values(Object.values(groupBy(arr, k)).map(x => ({
                            [k]: x[0][k],
                            [f]: x[0][f],
                            [b]: o
                            ? x.map(s => pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            })))

                            console.log(grp(data, 'countryID', 'country', 'schools'))





                            const data = [{ countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 142, studentName: "Mary" }, { countryID: 12, country: "US", schoolID: 122, schoolZone: "Highlands", studentID: 145, studentName: "John" }, { countryID: 14, country: "UK", schoolID: 222, schoolZone: "Leeds", studentID: 223, studentName: "Peter" } ];

                            const groupBy = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || , c], r), {})
                            const pick = (obj, fields) => fields.reduce((r,f) => (r[f] = obj[f], r), {})

                            const grp = (arr, k, f, b, o=0) =>
                            Object.values(Object.values(groupBy(arr, k)).map(x => ({
                            [k]: x[0][k],
                            [f]: x[0][f],
                            [b]: o
                            ? x.map(s => pick(s, ['studentID', 'studentName']))
                            : grp(x, 'schoolID', 'schoolZone', 'students', 1)
                            })))

                            console.log(grp(data, 'countryID', 'country', 'schools'))






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 24 '18 at 23:38

























                            answered Nov 24 '18 at 23:25









                            AkrionAkrion

                            9,45511224




                            9,45511224























                                0














                                First reshape each object to look like the final data structure:



                                reshape({
                                countryID: 12,
                                country: "US",
                                schoolID: 122,
                                schoolZone: "Highlands",
                                studentID: 142,
                                studentName: "Mary" });

                                //=> {
                                //=> country: "US",
                                //=> countryID: 12,
                                //=> schools: [
                                //=> {
                                //=> schoolID: 122,
                                //=> schoolZone: "Highlands",
                                //=> students: [
                                //=> {
                                //=> studentID: 142,
                                //=> studentName: "Mary"
                                //=> }
                                //=> ]
                                //=> }
                                //=> ]
                                //=> }


                                Then it is simply a matter of grouping by countries then by schools and using a map & reduce function to merge objects.






                                const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                const input = [
                                { countryID: 12,
                                country: "US",
                                schoolID: 122,
                                schoolZone: "Highlands",
                                studentID: 142,
                                studentName: "Mary" },

                                { countryID: 12,
                                country: "US",
                                schoolID: 122,
                                schoolZone: "Highlands",
                                studentID: 145,
                                studentName: "John" },

                                { countryID: 14,
                                country: "UK",
                                schoolID: 222,
                                schoolZone: "Leeds",
                                studentID: 223,
                                studentName: "Peter" }];

                                const reshape = applySpec({
                                countryID: prop('countryID'),
                                country: prop('country'),
                                schools: converge(
                                pipe(set(lensProp('students')), of), [
                                pipe(pick(['studentID', 'studentName']), of),
                                pick(['schoolID', 'schoolZone'])])
                                });

                                const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                const groupStudents = pipe(
                                groupBy(prop('schoolID')),
                                values,
                                map(reduce(mergeArrays('students'), {})));

                                const process = pipe(
                                map(reshape),
                                groupBy(prop('countryID')),
                                map(reduce(mergeArrays('schools'), {})),
                                map(over(lensProp('schools'), groupStudents)),
                                values);

                                console.log(process(input));

                                <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>








                                share|improve this answer






























                                  0














                                  First reshape each object to look like the final data structure:



                                  reshape({
                                  countryID: 12,
                                  country: "US",
                                  schoolID: 122,
                                  schoolZone: "Highlands",
                                  studentID: 142,
                                  studentName: "Mary" });

                                  //=> {
                                  //=> country: "US",
                                  //=> countryID: 12,
                                  //=> schools: [
                                  //=> {
                                  //=> schoolID: 122,
                                  //=> schoolZone: "Highlands",
                                  //=> students: [
                                  //=> {
                                  //=> studentID: 142,
                                  //=> studentName: "Mary"
                                  //=> }
                                  //=> ]
                                  //=> }
                                  //=> ]
                                  //=> }


                                  Then it is simply a matter of grouping by countries then by schools and using a map & reduce function to merge objects.






                                  const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                  const input = [
                                  { countryID: 12,
                                  country: "US",
                                  schoolID: 122,
                                  schoolZone: "Highlands",
                                  studentID: 142,
                                  studentName: "Mary" },

                                  { countryID: 12,
                                  country: "US",
                                  schoolID: 122,
                                  schoolZone: "Highlands",
                                  studentID: 145,
                                  studentName: "John" },

                                  { countryID: 14,
                                  country: "UK",
                                  schoolID: 222,
                                  schoolZone: "Leeds",
                                  studentID: 223,
                                  studentName: "Peter" }];

                                  const reshape = applySpec({
                                  countryID: prop('countryID'),
                                  country: prop('country'),
                                  schools: converge(
                                  pipe(set(lensProp('students')), of), [
                                  pipe(pick(['studentID', 'studentName']), of),
                                  pick(['schoolID', 'schoolZone'])])
                                  });

                                  const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                  const groupStudents = pipe(
                                  groupBy(prop('schoolID')),
                                  values,
                                  map(reduce(mergeArrays('students'), {})));

                                  const process = pipe(
                                  map(reshape),
                                  groupBy(prop('countryID')),
                                  map(reduce(mergeArrays('schools'), {})),
                                  map(over(lensProp('schools'), groupStudents)),
                                  values);

                                  console.log(process(input));

                                  <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>








                                  share|improve this answer




























                                    0












                                    0








                                    0







                                    First reshape each object to look like the final data structure:



                                    reshape({
                                    countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" });

                                    //=> {
                                    //=> country: "US",
                                    //=> countryID: 12,
                                    //=> schools: [
                                    //=> {
                                    //=> schoolID: 122,
                                    //=> schoolZone: "Highlands",
                                    //=> students: [
                                    //=> {
                                    //=> studentID: 142,
                                    //=> studentName: "Mary"
                                    //=> }
                                    //=> ]
                                    //=> }
                                    //=> ]
                                    //=> }


                                    Then it is simply a matter of grouping by countries then by schools and using a map & reduce function to merge objects.






                                    const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                    const input = [
                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" },

                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 145,
                                    studentName: "John" },

                                    { countryID: 14,
                                    country: "UK",
                                    schoolID: 222,
                                    schoolZone: "Leeds",
                                    studentID: 223,
                                    studentName: "Peter" }];

                                    const reshape = applySpec({
                                    countryID: prop('countryID'),
                                    country: prop('country'),
                                    schools: converge(
                                    pipe(set(lensProp('students')), of), [
                                    pipe(pick(['studentID', 'studentName']), of),
                                    pick(['schoolID', 'schoolZone'])])
                                    });

                                    const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                    const groupStudents = pipe(
                                    groupBy(prop('schoolID')),
                                    values,
                                    map(reduce(mergeArrays('students'), {})));

                                    const process = pipe(
                                    map(reshape),
                                    groupBy(prop('countryID')),
                                    map(reduce(mergeArrays('schools'), {})),
                                    map(over(lensProp('schools'), groupStudents)),
                                    values);

                                    console.log(process(input));

                                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>








                                    share|improve this answer















                                    First reshape each object to look like the final data structure:



                                    reshape({
                                    countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" });

                                    //=> {
                                    //=> country: "US",
                                    //=> countryID: 12,
                                    //=> schools: [
                                    //=> {
                                    //=> schoolID: 122,
                                    //=> schoolZone: "Highlands",
                                    //=> students: [
                                    //=> {
                                    //=> studentID: 142,
                                    //=> studentName: "Mary"
                                    //=> }
                                    //=> ]
                                    //=> }
                                    //=> ]
                                    //=> }


                                    Then it is simply a matter of grouping by countries then by schools and using a map & reduce function to merge objects.






                                    const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                    const input = [
                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" },

                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 145,
                                    studentName: "John" },

                                    { countryID: 14,
                                    country: "UK",
                                    schoolID: 222,
                                    schoolZone: "Leeds",
                                    studentID: 223,
                                    studentName: "Peter" }];

                                    const reshape = applySpec({
                                    countryID: prop('countryID'),
                                    country: prop('country'),
                                    schools: converge(
                                    pipe(set(lensProp('students')), of), [
                                    pipe(pick(['studentID', 'studentName']), of),
                                    pick(['schoolID', 'schoolZone'])])
                                    });

                                    const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                    const groupStudents = pipe(
                                    groupBy(prop('schoolID')),
                                    values,
                                    map(reduce(mergeArrays('students'), {})));

                                    const process = pipe(
                                    map(reshape),
                                    groupBy(prop('countryID')),
                                    map(reduce(mergeArrays('schools'), {})),
                                    map(over(lensProp('schools'), groupStudents)),
                                    values);

                                    console.log(process(input));

                                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>








                                    const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                    const input = [
                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" },

                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 145,
                                    studentName: "John" },

                                    { countryID: 14,
                                    country: "UK",
                                    schoolID: 222,
                                    schoolZone: "Leeds",
                                    studentID: 223,
                                    studentName: "Peter" }];

                                    const reshape = applySpec({
                                    countryID: prop('countryID'),
                                    country: prop('country'),
                                    schools: converge(
                                    pipe(set(lensProp('students')), of), [
                                    pipe(pick(['studentID', 'studentName']), of),
                                    pick(['schoolID', 'schoolZone'])])
                                    });

                                    const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                    const groupStudents = pipe(
                                    groupBy(prop('schoolID')),
                                    values,
                                    map(reduce(mergeArrays('students'), {})));

                                    const process = pipe(
                                    map(reshape),
                                    groupBy(prop('countryID')),
                                    map(reduce(mergeArrays('schools'), {})),
                                    map(over(lensProp('schools'), groupStudents)),
                                    values);

                                    console.log(process(input));

                                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>





                                    const {pick, map, groupBy, values, lensProp, over, reduce, mergeWithKey, pipe, prop, applySpec, converge, set, of} = R;

                                    const input = [
                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 142,
                                    studentName: "Mary" },

                                    { countryID: 12,
                                    country: "US",
                                    schoolID: 122,
                                    schoolZone: "Highlands",
                                    studentID: 145,
                                    studentName: "John" },

                                    { countryID: 14,
                                    country: "UK",
                                    schoolID: 222,
                                    schoolZone: "Leeds",
                                    studentID: 223,
                                    studentName: "Peter" }];

                                    const reshape = applySpec({
                                    countryID: prop('countryID'),
                                    country: prop('country'),
                                    schools: converge(
                                    pipe(set(lensProp('students')), of), [
                                    pipe(pick(['studentID', 'studentName']), of),
                                    pick(['schoolID', 'schoolZone'])])
                                    });

                                    const mergeArrays = key => mergeWithKey((k, a, b) => k === key ? [a[0], b[0]] : a);

                                    const groupStudents = pipe(
                                    groupBy(prop('schoolID')),
                                    values,
                                    map(reduce(mergeArrays('students'), {})));

                                    const process = pipe(
                                    map(reshape),
                                    groupBy(prop('countryID')),
                                    map(reduce(mergeArrays('schools'), {})),
                                    map(over(lensProp('schools'), groupStudents)),
                                    values);

                                    console.log(process(input));

                                    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>






                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Nov 25 '18 at 1:45

























                                    answered Nov 24 '18 at 13:47









                                    customcommandercustomcommander

                                    1,73111019




                                    1,73111019






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53457733%2fusing-lodash-groupby-to-normalise-objects%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        404 Error Contact Form 7 ajax form submitting

                                        How to know if a Active Directory user can login interactively

                                        Refactoring coordinates for Minecraft Pi buildings written in Python