I have some data listing teachers, subjects and students. I want to create a table with subjects associated with teachers where there must not be any repeating pair, but there might be a repeated teacher or repeated subject if the associated pair is not the same. This would be the data:
const data =
[
{
"teacher": "John Doe",
"subject": "Maths",
"student": "student1"
},
{
"teacher": "John Doe",
"subject": "Maths",
"student": "student2"
},
{
"teacher": "John Doe",
"subject": "Art",
"student": "student1"
},
{
"teacher": "Robert Wilson",
"subject": "History",
"student": "student1"
},
{
"teacher": "John Doe",
"subject": "Music",
"student": "student1"
},
{
"teacher": "Mark Smith",
"subject": "Maths",
"student": "student2"
},
{
"teacher": "Mary Martin",
"subject": "Science",
"student": "student1"
},
{
"teacher": "Mary Martin",
"subject": "Spanish",
"student": "student1"
},
{
"teacher": "Paula Wilson",
"subject": "Band",
"student": "student1"
},
{
"teacher": "Mark Smith",
"subject": "Band",
"student": "student2"
}
]
I have tried using the following code:
var subjectDict = {}
data.forEach (x => {
subjectDict [x.subject] = x.teacher
})
var teacherRow = Object.values (subjectDict)
var subjects = Object.keys (subjectDict)
However the output is not accurate because it gives me each subject just once even though it is taught by two different teachers (Band or Maths should appear twice associated with different teachers).
I have created a jsfiddle with the thing that I have tried:
https://jsfiddle.net/soleuil/f2r70Lte/1/
The solution should give me a table where the first row should be filled with the first element, and the last row should be filled with the second element (considering that the order can be different):
First Row : Second Row
"Maths":"John Doe"
"Art":"John Doe"
"History":"Robert Wilson"
"Music":"John Doe"
"Maths":"Mark Smith"
"Science":"Mary Martin"
"Spanish": "Mary Martin"
"Band":"Paula Wilson"
"Band":"Mark Smith"
Thank you in advance.
CodePudding user response:
This will give you the subject as a key with an array of associated teachers with the output:
{
"Maths": [ "John Doe", "Mark Smith" ],
"Art": [ "John Doe" ],
"History": [ "Robert Wilson" ],
"Music": [ "John Doe" ],
"Science": [ "Mary Martin" ],
"Spanish": [ "Mary Martin" ],
"Band": [ "Paula Wilson", "Mark Smith" ]
}
const data = [ { "teacher": "John Doe", "subject": "Maths", "student": "student1" }, { "teacher": "John Doe", "subject": "Maths", "student": "student2" }, { "teacher": "John Doe", "subject": "Art", "student": "student1" }, { "teacher": "Robert Wilson", "subject": "History", "student": "student1" }, { "teacher": "John Doe", "subject": "Music", "student": "student1" }, { "teacher": "Mark Smith", "subject": "Maths", "student": "student2" }, { "teacher": "Mary Martin", "subject": "Science", "student": "student1" }, { "teacher": "Mary Martin", "subject": "Spanish", "student": "student1" }, { "teacher": "Paula Wilson", "subject": "Band", "student": "student1" }, { "teacher": "Mark Smith", "subject": "Band", "student": "student2" } ];
let subject_teachers = data.reduce((b, a) => {
if (!b[a.subject]) b[a.subject] = [];
if (b[a.subject].indexOf(a.teacher) == -1) b[a.subject].push(a.teacher);
return b;
}, {})
console.log(subject_teachers)
CodePudding user response:
Using Array#reduce
:
const data = [ { "teacher": "John Doe", "subject": "Maths", "student": "student1" }, { "teacher": "John Doe", "subject": "Maths", "student": "student2" }, { "teacher": "John Doe", "subject": "Art", "student": "student1" }, { "teacher": "Robert Wilson", "subject": "History", "student": "student1" }, { "teacher": "John Doe", "subject": "Music", "student": "student1" }, { "teacher": "Mark Smith", "subject": "Maths", "student": "student2" }, { "teacher": "Mary Martin", "subject": "Science", "student": "student1" }, { "teacher": "Mary Martin", "subject": "Spanish", "student": "student1" }, { "teacher": "Paula Wilson", "subject": "Band", "student": "student1" }, { "teacher": "Mark Smith", "subject": "Band", "student": "student2" } ];
const [subjects, teachers] = data.reduce(([subjects, teachers], { subject, teacher }) => {
const subjectIndex = subjects.indexOf(subject);
const exists = subjectIndex >= 0 && teachers[subjectIndex] === teacher;
return exists
? [subjects, teachers]
: [ [...subjects, subject], [...teachers, teacher] ];
}, [ [], [] ]);
console.log(subjects);
console.log(teachers);
CodePudding user response:
Based on your desired output, I would slightly modify your code to return an array of objects.
const data =
[
{
"teacher": "John Doe",
"subject": "Maths",
"student": "student1"
},
{
"teacher": "John Doe",
"subject": "Maths",
"student": "student2"
},
{
"teacher": "John Doe",
"subject": "Art",
"student": "student1"
},
{
"teacher": "Robert Wilson",
"subject": "History",
"student": "student1"
},
{
"teacher": "John Doe",
"subject": "Music",
"student": "student1"
},
{
"teacher": "Mark Smith",
"subject": "Maths",
"student": "student2"
},
{
"teacher": "Mary Martin",
"subject": "Science",
"student": "student1"
},
{
"teacher": "Mary Martin",
"subject": "Spanish",
"student": "student1"
},
{
"teacher": "Paula Wilson",
"subject": "Band",
"student": "student1"
},
{
"teacher": "Mark Smith",
"subject": "Band",
"student": "student2"
}
];
var subjectDict = data.map (function(x) {
temp = {};
temp[x.subject] = x.teacher;
return temp;
});
console.log(subjectDict);