How to change a format of an output?

Viewed 76

I have a task to filter an array of students with the same 'matrikelnummer' property. I am getting below output now:

{
  4251: [
    {
      adresse: "900 Mitchell Trail",
      course: "Medientechnik",
      email: "mciccottio0@bandcamp.com",
      matrikelnummer: 4251,
      nachname: "Ciccottio",
      phone: "(533) 9776037",
      semester: 5,
      vorname: "Médiamass"
    }, {
      adresse: "7224 Tennessee Hill",
      course: "Medieninformatik",
      email: "sellingworth1@home.pl",
      matrikelnummer: 4251,
      nachname: "Ellingworth",
      phone: "(129) 5071723",
      semester: 4,
      vorname: "Tán"
    }, {
      adresse: "287 Daystar Park",
      course: "Informatik",
      email: "sreape2@ning.com",
      matrikelnummer: 4251,
      nachname: "Reape",
      phone: "(189) 8272285",
      semester: 12,
      vorname: "Gisèle"
    }
  ],
  4315: [
    {
      adresse: "4910 Rieder Hill",
      course: "Informatik",
      email: "jsizland4@hud.gov",
      matrikelnummer: 4315,
      nachname: "Sizland",
      phone: "(859) 3523116",
      semester: 2,
      vorname: "Méline"
    }
  ],
  4556: [
    {
      adresse: "17143 Monument Junction",
      course: "Wirtschaftsinformatik",
      email: "tkingsworth3@google.co.uk",
      matrikelnummer: 4556,
      nachname: "Kingsworth",
      phone: "(517) 1329873",
      semester: 8,
      vorname: "Styrbjörn"
    }
  ]
}

but I should format it to something like this:


[
  {
    "matrikelnummer": 4250, 
    "students":[
      {
        "matrikelnummer":4250,
        "vorname":"Gérald", 
        "nachname":"Bayston", 
        "adresse":"3 Tony Street",
        "course":"Informatik", 
        "semester":5, 
        "email":"wbayston3x@cmu.edu",
        "phone":"(404) 3665176"
      }, 
      {
        "matrikelnummer":4250, 
        "vorname":"Wá",
        "nachname":"Chasney",
        "adresse":"919 Iowa Place",
        "course":"Wirtschaftsinformatik", 
        "semester":2,
        "email":"mchasneydd@nasa.gov", 
        "phone":"(510) 1079563"
      },
      {
        "matrikelnummer":4250, 
        "vorname":"Östen", 
        "nachname":"Heggman",
        "adresse":"8 Coleman Drive", 
        "course":"Medieninformatik",
        "semester":1, 
        "email":"kheggman9j@buzzfeed.com", 
        "phone":"(381)8246163"
      }, 
      {
        "matrikelnummer":4250, 
        "vorname":"Vérane", 
        "nachname":"Roubert", 
        "adresse":"463 Lakewood Avenue",
        "course":"Medientechnik", 
        "semester":5,
        "email":"aroubert7r@cornell.edu", 
        "phone":"(625) 8344564"
      }
    ]
  }
]

Do you know how can I resolve that issue? Here is my current code:

var students = [{"matrikelnummer":4251,"vorname":"Médiamass","nachname":"Ciccottio","adresse":"900 Mitchell Trail","course":"Medientechnik","semester":5,"email":"mciccottio0@bandcamp.com","phone":"(533) 9776037"},
{"matrikelnummer":4251,"vorname":"Tán","nachname":"Ellingworth","adresse":"7224 Tennessee Hill","course":"Medieninformatik","semester":4,"email":"sellingworth1@home.pl","phone":"(129) 5071723"},
{"matrikelnummer":4251,"vorname":"Gisèle","nachname":"Reape","adresse":"287 Daystar Park","course":"Informatik","semester":12,"email":"sreape2@ning.com","phone":"(189) 8272285"},
{"matrikelnummer":4556,"vorname":"Styrbjörn","nachname":"Kingsworth","adresse":"17143 Monument Junction","course":"Wirtschaftsinformatik","semester":8,"email":"tkingsworth3@google.co.uk","phone":"(517) 1329873"},
{"matrikelnummer":4315,"vorname":"Méline","nachname":"Sizland","adresse":"4910 Rieder Hill","course":"Informatik","semester":2,"email":"jsizland4@hud.gov","phone":"(859) 3523116"}]

const duplicateStudents = (students) => {
  const grouping = students.reduce((previous, current) => {
    if (previous[current.matrikelnummer]) previous[current.matrikelnummer].push(current);
    else previous[current.matrikelnummer] = [current];
    return previous;
  }, {});

  return grouping
};
3 Answers

The concept is simple. You just need to loop over the students and check for an existing object with the same matrikelnummber. If yes, push to students array. Or else, just create one. The approach is better with JavaScript's reduce:

var students = [{
    "matrikelnummer": 4251,
    "vorname": "Médiamass",
    "nachname": "Ciccottio",
    "adresse": "900 Mitchell Trail",
    "course": "Medientechnik",
    "semester": 5,
    "email": "mciccottio0@bandcamp.com",
    "phone": "(533) 9776037"
  },
  {
    "matrikelnummer": 4251,
    "vorname": "Tán",
    "nachname": "Ellingworth",
    "adresse": "7224 Tennessee Hill",
    "course": "Medieninformatik",
    "semester": 4,
    "email": "sellingworth1@home.pl",
    "phone": "(129) 5071723"
  },
  {
    "matrikelnummer": 4251,
    "vorname": "Gisèle",
    "nachname": "Reape",
    "adresse": "287 Daystar Park",
    "course": "Informatik",
    "semester": 12,
    "email": "sreape2@ning.com",
    "phone": "(189) 8272285"
  },
  {
    "matrikelnummer": 4556,
    "vorname": "Styrbjörn",
    "nachname": "Kingsworth",
    "adresse": "17143 Monument Junction",
    "course": "Wirtschaftsinformatik",
    "semester": 8,
    "email": "tkingsworth3@google.co.uk",
    "phone": "(517) 1329873"
  },
  {
    "matrikelnummer": 4315,
    "vorname": "Méline",
    "nachname": "Sizland",
    "adresse": "4910 Rieder Hill",
    "course": "Informatik",
    "semester": 2,
    "email": "jsizland4@hud.gov",
    "phone": "(859) 3523116"
  }
]

let result = students.reduce((studentArray, student, index) => {
  let existingStudent = studentArray.find(studentIteration =>
    studentIteration.matrikelnummer === student.matrikelnummer
  );
  if (existingStudent) {
    existingStudent.students.push(student);
  } else {
    studentArray.push({
      matrikelnummer: student.matrikelnummer,
      students: [student]
    });
  }
  return studentArray;
}, []);

console.log(result);

The previous answer has a direct, transparent approach. Use Array.reduce and within that use Array.find in order to obtain the target/result array.

The below approach (breaks down the problem into two smaller problems and) uses a two-staged approach, instead.

Stage-1: Generate an object with key as the matrikelnummer and value as an Array (of students who have the same matrikelnummer, ie, duplicates).

Stage-2: Convert the object created at Stage-1 into an Array which matches the target/expected result.

const students = [{
    "matrikelnummer": 4251,
    "vorname": "Médiamass",
    "nachname": "Ciccottio",
    "adresse": "900 Mitchell Trail",
    "course": "Medientechnik",
    "semester": 5,
    "email": "mciccottio0@bandcamp.com",
    "phone": "(533) 9776037"
  },
  {
    "matrikelnummer": 4251,
    "vorname": "Tán",
    "nachname": "Ellingworth",
    "adresse": "7224 Tennessee Hill",
    "course": "Medieninformatik",
    "semester": 4,
    "email": "sellingworth1@home.pl",
    "phone": "(129) 5071723"
  },
  {
    "matrikelnummer": 4251,
    "vorname": "Gisèle",
    "nachname": "Reape",
    "adresse": "287 Daystar Park",
    "course": "Informatik",
    "semester": 12,
    "email": "sreape2@ning.com",
    "phone": "(189) 8272285"
  },
  {
    "matrikelnummer": 4556,
    "vorname": "Styrbjörn",
    "nachname": "Kingsworth",
    "adresse": "17143 Monument Junction",
    "course": "Wirtschaftsinformatik",
    "semester": 8,
    "email": "tkingsworth3@google.co.uk",
    "phone": "(517) 1329873"
  },
  {
    "matrikelnummer": 4315,
    "vorname": "Méline",
    "nachname": "Sizland",
    "adresse": "4910 Rieder Hill",
    "course": "Informatik",
    "semester": 2,
    "email": "jsizland4@hud.gov",
    "phone": "(859) 3523116"
  }
]

const filterAndFormat = (students) => (
  Object.entries(
    students.reduce(
      (fin, itm) => ({ ...fin,
        [itm.matrikelnummer]: (fin[itm.matrikelnummer] || []).concat([itm])
      }), {}))
  .map(
    ([k, v]) => ({
      matrikelnummer: k,
      students: v
    })));

console.log(filterAndFormat(students));

The only thing missing from your current solution is the final transformation:

return Object.entries(grouping).map(
  ([matrikelnummer, students]) => ({ matrikelnummer, students })
);

var students = [{"matrikelnummer":4251,"vorname":"Médiamass","nachname":"Ciccottio","adresse":"900 Mitchell Trail","course":"Medientechnik","semester":5,"email":"mciccottio0@bandcamp.com","phone":"(533) 9776037"},
{"matrikelnummer":4251,"vorname":"Tán","nachname":"Ellingworth","adresse":"7224 Tennessee Hill","course":"Medieninformatik","semester":4,"email":"sellingworth1@home.pl","phone":"(129) 5071723"},
{"matrikelnummer":4251,"vorname":"Gisèle","nachname":"Reape","adresse":"287 Daystar Park","course":"Informatik","semester":12,"email":"sreape2@ning.com","phone":"(189) 8272285"},
{"matrikelnummer":4556,"vorname":"Styrbjörn","nachname":"Kingsworth","adresse":"17143 Monument Junction","course":"Wirtschaftsinformatik","semester":8,"email":"tkingsworth3@google.co.uk","phone":"(517) 1329873"},
{"matrikelnummer":4315,"vorname":"Méline","nachname":"Sizland","adresse":"4910 Rieder Hill","course":"Informatik","semester":2,"email":"jsizland4@hud.gov","phone":"(859) 3523116"}]

const duplicateStudents = (students) => {
  const grouping = students.reduce((previous, current) => {
    if (previous[current.matrikelnummer]) previous[current.matrikelnummer].push(current);
    else previous[current.matrikelnummer] = [current];
    return previous;
  }, {});
    
  return Object.entries(grouping).map(
    ([matrikelnummer, students]) => ({ matrikelnummer, students })
  );
};

console.log(duplicateStudents(students));

Which converts the resulting grouping into an array of key/value-pairs, then maps each pair into an object with the desired keys.


There is also the option to build the desired result together with the groupings (renamed to lookup in the example below) in a single iteration. The example below uses a Map instance instead of an object, but the principal is the same.

const duplicateStudents = (students) => {
  const result = [];
  const lookup = new Map();
  
  for (const student of students) {
    const matrikelnummer = student.matrikelnummer;
    if (!lookup.has(matrikelnummer)) {
      const students = [];
      result.push({ matrikelnummer, students });
      lookup.set(matrikelnummer, students);
    }
    lookup.get(matrikelnummer).push(student);
  }
  
  return result;
};

var students = [{"matrikelnummer":4251,"vorname":"Médiamass","nachname":"Ciccottio","adresse":"900 Mitchell Trail","course":"Medientechnik","semester":5,"email":"mciccottio0@bandcamp.com","phone":"(533) 9776037"},
{"matrikelnummer":4251,"vorname":"Tán","nachname":"Ellingworth","adresse":"7224 Tennessee Hill","course":"Medieninformatik","semester":4,"email":"sellingworth1@home.pl","phone":"(129) 5071723"},
{"matrikelnummer":4251,"vorname":"Gisèle","nachname":"Reape","adresse":"287 Daystar Park","course":"Informatik","semester":12,"email":"sreape2@ning.com","phone":"(189) 8272285"},
{"matrikelnummer":4556,"vorname":"Styrbjörn","nachname":"Kingsworth","adresse":"17143 Monument Junction","course":"Wirtschaftsinformatik","semester":8,"email":"tkingsworth3@google.co.uk","phone":"(517) 1329873"},
{"matrikelnummer":4315,"vorname":"Méline","nachname":"Sizland","adresse":"4910 Rieder Hill","course":"Informatik","semester":2,"email":"jsizland4@hud.gov","phone":"(859) 3523116"}]

const duplicateStudents = (students) => {
  const result = [];
  const lookup = new Map();
  
  for (const student of students) {
    const matrikelnummer = student.matrikelnummer;
    if (!lookup.has(matrikelnummer)) {
      const students = [];
      result.push({ matrikelnummer, students });
      lookup.set(matrikelnummer, students);
    }
    lookup.get(matrikelnummer).push(student);
  }
  
  return result;
};

console.log(duplicateStudents(students));

This might somewhat harder to understand. The following line:

lookup.get(matrikelnummer).push(student);

Pushes a student into a group. It is important to note that the group is present in both result and lookup. So when we push a new student into the group via lookup, the contents of result also change—because they both refer to the same array.

Related