C# Project: Grade Report
The Grade Report project turns raw scores into one average line per student. It groups the rows, sorts the names, prints the report, and saves it to a file.
Group Rows by Student
Rows for Ben and Anya repeat across the list. The groups print in name order with one average each.
using System;
using System.Collections.Generic;
using System.Linq;
record Student(string Name, int Score);
class Program
{
static void Main(string[] args)
{
List<Student> rows = new List<Student>
{
new Student("Ben", 70),
new Student("Anya", 80),
new Student("Ben", 80),
new Student("Anya", 90)
};
var groups = rows.GroupBy(r => r.Name).OrderBy(g => g.Key);
foreach (var group in groups)
{
Console.WriteLine(group.Key + ": " + group.Average(r => r.Score));
}
}
}Build the Report Lines
The loop adds one line per group to a list. A second loop prints the finished lines.
using System;
using System.Collections.Generic;
using System.Linq;
record Student(string Name, int Score);
class Program
{
static void Main(string[] args)
{
List<Student> rows = new List<Student>
{
new Student("Dan", 60),
new Student("Cara", 90),
new Student("Dan", 80),
new Student("Cara", 100)
};
var groups = rows.GroupBy(r => r.Name).OrderBy(g => g.Key);
List<string> lines = new List<string>();
foreach (var group in groups)
{
lines.Add(group.Key + ": " + group.Average(r => r.Score));
}
foreach (string line in lines)
{
Console.WriteLine(line);
}
}
}Save and Count the Lines
The report lines go to a file with WriteAllLines. ReadAllLines loads them back so the program can count them.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
record Student(string Name, int Score);
class Program
{
static void Main(string[] args)
{
List<Student> rows = new List<Student>
{
new Student("Fay", 70),
new Student("Eli", 80),
new Student("Fay", 90),
new Student("Eli", 100)
};
var groups = rows.GroupBy(r => r.Name).OrderBy(g => g.Key);
List<string> lines = new List<string>();
foreach (var group in groups)
{
lines.Add(group.Key + ": " + group.Average(r => r.Score));
}
foreach (string line in lines)
{
Console.WriteLine(line);
}
File.WriteAllLines("report.txt", lines);
string[] saved = File.ReadAllLines("report.txt");
Console.WriteLine("Saved lines: " + saved.Length);
}
}Example
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
record Student(string Name, int Score);
class Program
{
static void Main(string[] args)
{
List<Student> rows = new List<Student>
{
new Student("Zoe", 90),
new Student("Maya", 80),
new Student("Liam", 70),
new Student("Zoe", 100),
new Student("Maya", 90),
new Student("Liam", 85),
new Student("Zoe", 80)
};
var groups = rows.GroupBy(r => r.Name).OrderBy(g => g.Key);
List<string> lines = new List<string>();
foreach (var group in groups)
{
lines.Add(group.Key + ": " + group.Average(r => r.Score));
}
foreach (string line in lines)
{
Console.WriteLine(line);
}
File.WriteAllLines("grade-report.txt", lines);
string[] saved = File.ReadAllLines("grade-report.txt");
Console.WriteLine("Saved lines: " + saved.Length);
}
}Key points
- A Student record holds a name and a score for one row.
- GroupBy collects the rows that share the same student name.
- Average gives the mean score of each group.
- OrderBy sorts the groups by student name.
- Each report line holds one name and its average.
- File.WriteAllLines saves the report lines to a file.
- File.ReadAllLines reads the saved file back for a count check.
In this example, seven rows hold scores for Zoe, Maya, and Liam. GroupBy collects the rows of each student into one group. Average turns each group into one clean number. OrderBy puts the groups in name order, so Liam prints before Maya and Zoe. The program prints each report line, saves the lines with WriteAllLines, and confirms the saved count with ReadAllLines.
Note
This project uses only tools from earlier lessons.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
The scores for Anya are 80 and 100. Which line does the report hold for Anya?