问题描述
我有以下表作为我的输入.
+--------+---------+-------+ | Name | Course | Score | +--------+---------+-------+ | John | Math | 5 | | Hannah | Math | 4 | | Lilly | Math | 5 | | John | Science | 5 | | Hannah | Science | 5 | | Lilly | Science | 5 | | John | Social | 5 | | Hannah | Social | 4 | | Lilly | Social | 3 | +--------+---------+-------+
作为输出,我想拥有一张表格,可以显示名称,总分,得分平均值和星星.明星将是学生得分5/5的次数.因此,例如,约翰应该有3颗星,而汉娜应该有1星,莉莉应该有2.基本上,我想将下表作为我的输出:
+--------+-------+---------+------+ | Name | Score | Average | Star | +--------+-------+---------+------+ | John | 15 | 5 | 3 | | Hannah | 13 | 4.3 | 1 | | Lilly | 13 | 4.3 | 2 | +--------+-------+---------+------+
我能够获得得分和平均水平,但我无法弄清楚如何做星星.从编程上讲,我认为我需要按名称进行分组,然后计算重复的数字,我认为应该在LINQ中完成,但我不确定该怎么做:
这是我的代码:
public string Name { get; private set; } public int Score { get; set; } public decimal Average { get; set; } public decimal Count { get; set; } public Person(string name, int score, decimal avg, int count) { Name = name; Score = score; Average = avg; Count = count; } public ObservableCollection<Person> Persons { get; set; } filepath = scoresFile; public MainWindow() { InitializeComponent(); LoadTable(); } private void datagrid_Sorting(object sender, DataGridSortingEventArgs e) { if (e.Column.Header.Equals("Name") || e.Column.Header.Equals("Score")) { e.Handled = true; } } public void LoadTable() { var lines = File.ReadAllLines(filepath); Persons = new ObservableCollection<Person>(); var data = lines.Select(line => { var column = line.Split(','); int c = column[1].Count(); var name = column[1]; int score = int.Parse(column[3]); decimal avg = decimal.Parse(column[3]); int count = 0; return new { name, score, avg, count}; } ); var groupedData = data.GroupBy(p => p.name) .Select((g, i) => new { num= 0, name = g.Key, score = g.Sum(p => p.score), avg = decimal.Round(g.Average(p => p.avg), 1), count = g.Count() }) .OrderByDescending(x => x.avg); var persons = groupedData.Select((p, i) => new Person(i + 1, p.name, p.score, p.avg, p.count)); foreach (var person in persons) { Persons.Add(person); } datagrid.ItemsSource = Persons; }
我一直在尝试对Linq系列进行一些修改,但我认为这不是一个好主意:
var groupedData = data.GroupBy(p => p.name, s=> s.score ) .Where(p => p.Count() > 5).Select((g, i) => new { num= 0, name = g.Key, rank = i + 1, score = g.Sum(p => p.score), avg = decimal.Round(g.Average(p => p.avg), 1), count = g.Count() }) .OrderByDescending(x => x.avg);
然后,我想到添加以下行并调用num,但这也没有起作用.
var num = data.GroupBy(p => p.name, p =p.score).Any(g => g.Count() > 1);
有什么想法?
推荐答案
您可以在计数之前使用子句. 尝试以下查询
var Output = StudentCourseDetails.GroupBy(a => a.Name).Select(ag => new { Name = ag.Key, Score = ag.Sum( i => i.Score), Average = ag.Average(i => i.Score), Star = ag.Where(i=> i.Score == 5).Count() });
其他推荐答案
您可以尝试一下,您不需要分数,因为您想总结所有这些,并且要计算收到的5星数,您只需要做
var data = from std in students group by std.Name into grp select new { name = grp.key, score = grp.Sum(s=> s.Score), avg = decimal.Round(grp.Average(s => s.avg), 1), star = grp.Count(s=> s.Score == 5) Report = ReviewText(grp.Count(s=> s.Score == 5) ) }; private string ReviewText(int count) { if(count >= 3) return "Excellent"; else if (count ==2) return "Good"; else return string.Empty; }
或其他方式
var Output = students.GroupBy(std => std.Name) .Select(grp => new { Name = grp.Key, Score = grp.Sum( i => i.Score), Average = decimal.Round(grp.Average(s => s.avr),1), Star = grp.Count(i=> i.Score == 5) });
其他推荐答案
以下代码将对您有所帮助,
var result = (from s in data group s by s.Name into grp select new { name = grp.Key, score = grp.Sum(s=> s.Score), avg = decimal.Round(grp.Average(s =>Convert.ToDecimal(s.Score)),1,MidpointRounding.AwayFromZero), star = grp.Where(s=> s.Score == 5).Count() }).ToList(); Console.WriteLine(result);
或
var result = data.GroupBy(s=>s.Name).Select(g=>new{g.Key,score = g.Sum(s=> s.Score),avg= decimal.Round(g.Average(s =>Convert.ToDecimal(s.Score)),1,MidpointRounding.AwayFromZero),star = g.Where(s=> s.Score == 5).Count()}); Console.WriteLine(result);
问题描述
I have the below table as my input.
+--------+---------+-------+ | Name | Course | Score | +--------+---------+-------+ | John | Math | 5 | | Hannah | Math | 4 | | Lilly | Math | 5 | | John | Science | 5 | | Hannah | Science | 5 | | Lilly | Science | 5 | | John | Social | 5 | | Hannah | Social | 4 | | Lilly | Social | 3 | +--------+---------+-------+
and as an output, I want to have a table that will show the name, total score, average of the score and star. The star will be the number of times the student scored 5/5. So for example, John should have 3 stars, whereas Hannah should have 1 and Lilly should have 2. Basically, I want to have the below table as my output:
+--------+-------+---------+------+ | Name | Score | Average | Star | +--------+-------+---------+------+ | John | 15 | 5 | 3 | | Hannah | 13 | 4.3 | 1 | | Lilly | 13 | 4.3 | 2 | +--------+-------+---------+------+
I was able to get the score and average, but i just cant figure out how to do the stars part. Programatically, I think i need to group by names and then count duplicated numbers, and I think it should be done in linq but i am not sure how to do that yet:
Here's my code:
public string Name { get; private set; } public int Score { get; set; } public decimal Average { get; set; } public decimal Count { get; set; } public Person(string name, int score, decimal avg, int count) { Name = name; Score = score; Average = avg; Count = count; } public ObservableCollection<Person> Persons { get; set; } filepath = scoresFile; public MainWindow() { InitializeComponent(); LoadTable(); } private void datagrid_Sorting(object sender, DataGridSortingEventArgs e) { if (e.Column.Header.Equals("Name") || e.Column.Header.Equals("Score")) { e.Handled = true; } } public void LoadTable() { var lines = File.ReadAllLines(filepath); Persons = new ObservableCollection<Person>(); var data = lines.Select(line => { var column = line.Split(','); int c = column[1].Count(); var name = column[1]; int score = int.Parse(column[3]); decimal avg = decimal.Parse(column[3]); int count = 0; return new { name, score, avg, count}; } ); var groupedData = data.GroupBy(p => p.name) .Select((g, i) => new { num= 0, name = g.Key, score = g.Sum(p => p.score), avg = decimal.Round(g.Average(p => p.avg), 1), count = g.Count() }) .OrderByDescending(x => x.avg); var persons = groupedData.Select((p, i) => new Person(i + 1, p.name, p.score, p.avg, p.count)); foreach (var person in persons) { Persons.Add(person); } datagrid.ItemsSource = Persons; }
I have been trying to make some modifications to the linq line but i dont think it would be a good idea:
var groupedData = data.GroupBy(p => p.name, s=> s.score ) .Where(p => p.Count() > 5).Select((g, i) => new { num= 0, name = g.Key, rank = i + 1, score = g.Sum(p => p.score), avg = decimal.Round(g.Average(p => p.avg), 1), count = g.Count() }) .OrderByDescending(x => x.avg);
then i thought of adding the below line and calling num, but that didnt work either.
var num = data.GroupBy(p => p.name, p =p.score).Any(g => g.Count() > 1);
any ideas?
推荐答案
You can use where clause before taking count. Try below query
var Output = StudentCourseDetails.GroupBy(a => a.Name).Select(ag => new { Name = ag.Key, Score = ag.Sum( i => i.Score), Average = ag.Average(i => i.Score), Star = ag.Where(i=> i.Score == 5).Count() });
其他推荐答案
can you try this out , you dont need group on score as you want to sum all of them and for counting number of 5 star received you just need to do count of it
var data = from std in students group by std.Name into grp select new { name = grp.key, score = grp.Sum(s=> s.Score), avg = decimal.Round(grp.Average(s => s.avg), 1), star = grp.Count(s=> s.Score == 5) Report = ReviewText(grp.Count(s=> s.Score == 5) ) }; private string ReviewText(int count) { if(count >= 3) return "Excellent"; else if (count ==2) return "Good"; else return string.Empty; }
or other way
var Output = students.GroupBy(std => std.Name) .Select(grp => new { Name = grp.Key, Score = grp.Sum( i => i.Score), Average = decimal.Round(grp.Average(s => s.avr),1), Star = grp.Count(i=> i.Score == 5) });
其他推荐答案
Following code will be helpful to you,
var result = (from s in data group s by s.Name into grp select new { name = grp.Key, score = grp.Sum(s=> s.Score), avg = decimal.Round(grp.Average(s =>Convert.ToDecimal(s.Score)),1,MidpointRounding.AwayFromZero), star = grp.Where(s=> s.Score == 5).Count() }).ToList(); Console.WriteLine(result);
Or
var result = data.GroupBy(s=>s.Name).Select(g=>new{g.Key,score = g.Sum(s=> s.Score),avg= decimal.Round(g.Average(s =>Convert.ToDecimal(s.Score)),1,MidpointRounding.AwayFromZero),star = g.Where(s=> s.Score == 5).Count()}); Console.WriteLine(result);