Ad
How To Group And Sum Up In A LINQ Like Manner In JavaScript
I'm getting crazy about that. Maybe you could help.
Assume having the following .NET classes:
Teacher:
public class Teacher
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Class[] Classes { get; set; }
}
Class
public class Class
{
public int Id { get; set; }
public string Name { get; set; }
public Attendee[] Attendees { get; set; }
}
Attendee
public class Attendee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Presences { get; set; }
}
According to this structure we take the following data for example:
var teachers =
new Teacher[] {
new Teacher{ Id = 1, FirstName="Michael", LastName = "Knight",
Classes = new Class[]{
new Class{ Id = 1, Name = "Maths",
Attendees = new Attendee[]{
new Attendee{ Id = 1, FirstName = "Templeton", LastName = "Peck", Presences=22 },
new Attendee{ Id = 2, FirstName = "Stringfellow", LastName = "Hawke", Presences=20 }
}
},
new Class{ Id = 1, Name = "English",
Attendees = new Attendee[]{
new Attendee{ Id = 3, FirstName = "Morris", LastName = "Buttermaker", Presences=25 },
new Attendee{ Id = 4, FirstName = "Ben", LastName = "Matlock", Presences=18 },
new Attendee{ Id = 5, FirstName = "Kelly", LastName = "Taylor", Presences=22 },
new Attendee{ Id = 5, FirstName = "Marty", LastName = "McFly", Presences=0 }
}
}
}
},
new Teacher{ Id = 2, FirstName="Murray", LastName = "Bozinsky",
Classes = new Class[]{
new Class{ Id = 1, Name = "Maths",
Attendees = new Attendee[]{
new Attendee{ Id = 6, FirstName = "Luke", LastName = "Duke", Presences=21 },
new Attendee{ Id = 7, FirstName = "Bo", LastName = "Darville", Presences=26 },
new Attendee{ Id = 8, FirstName = "Frank", LastName = "Columbo", Presences=20 }
}
},
new Class{ Id = 1, Name = "English",
Attendees = new Attendee[]{
new Attendee{ Id = 9, FirstName = "Philip", LastName = "Banks", Presences=28 },
new Attendee{ Id = 10, FirstName = "Lynn", LastName = "Tanner", Presences=18 }
}
}
}
}
};
What I now want to do, is to sum up all presences of a teachers attendees. In LINQ I would do this like that:
var result = teachers
.Select(p =>
new {
TeacherFirstName = p.FirstName,
TeacherLastName = p.LastName,
Presences = p.Classes
.SelectMany(q => q.Attendees.Select(r => r.Presences))
.Sum() });
Which gives me (as JSON):
[
{"TeacherFirstName":"Michael","TeacherLastName":"Knight","Presences":107},
{"TeacherFirstName":"Murray","TeacherLastName":"Bozinsky","Presences":113}
]
How could I do this with JavaScript taking the following JSON object:
[
{
"Id":1,"FirstName":"Michael","LastName":"Knight",
"Classes":
[
{
"Id":1,"Name":"Maths",
"Attendees":
[
{"Id":1,"FirstName":"Templeton","LastName":"Peck","Presences":22},
{"Id":2,"FirstName":"Stringfellow","LastName":"Hawke","Presences":20}
]
},
{
"Id":1,"Name":"English",
"Attendees":
[
{"Id":3,"FirstName":"Morris","LastName":"Buttermaker","Presences":25},
{"Id":4,"FirstName":"Ben","LastName":"Matlock","Presences":18},
{"Id":5,"FirstName":"Kelly","LastName":"Taylor","Presences":22},
{"Id":5,"FirstName":"Marty","LastName":"McFly","Presences":0}
]
}
]
},
{
"Id":2,"FirstName":"Murray","LastName":"Bozinsky",
"Classes":
[
{
"Id":1,"Name":"Maths",
"Attendees":
[
{"Id":6,"FirstName":"Luke","LastName":"Duke","Presences":21},
{"Id":7,"FirstName":"Bo","LastName":"Darville","Presences":26},
{"Id":8,"FirstName":"Frank","LastName":"Columbo","Presences":20}
]
},
{
"Id":1,"Name":"English",
"Attendees":
[
{"Id":9,"FirstName":"Philip","LastName":"Banks","Presences":28},
{"Id":10,"FirstName":"Lynn","LastName":"Tanner","Presences":18}
]
}
]
}
]
I was playing arround with reduce
and map
. But I just can't get it working. Do you have a hint, how this can be done in a one- (or two-, or three-, ...)liner?
Thank you in advance.
Ad
Answer
Sure. A single map expression:
const transformed = data.map(
({ FirstName, LastName, Classes }) => ({
TeacherFirstName: FirstName,
TeacherLastName: LastName,
Presences: Classes.map(c =>
c.Attendees.reduce(
(acc, { Presences }) => acc + Presences,
0,
),
).reduce((acc, value) => acc + value, 0),
}),
);
results in
[
{
TeacherFirstName: 'Michael',
TeacherLastName: 'Knight',
Presences: 107
},
{
TeacherFirstName: 'Murray',
TeacherLastName: 'Bozinsky',
Presences: 113
}
]
Adding a helper function for summing an array of numbers makes things arguably more readable than using reduces:
const sum = numbers => numbers.reduce((acc, n) => acc + n, 0);
const transformed = data.map(
({ FirstName, LastName, Classes }) => ({
TeacherFirstName: FirstName,
TeacherLastName: LastName,
Presences: sum(
Classes.map(c => sum(c.Attendees.map(a => a.Presences))),
),
}),
);
Ad
source: stackoverflow.com
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
Ad