我将下表作为输入。
+--------+---------+-------+
| 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的次数。所以例如,John应该有3颗星,而Hannah应该有1颗,而Lilly应该有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);
任何想法?
答案 0 :(得分:2)
您可以在计算之前使用where子句。 请尝试以下查询
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()
});
答案 1 :(得分:1)
你可以尝试一下吗,你不需要分组,因为你想要总结所有这些和计算5星的数量你只需要计算它
from itertools import chain
list_1 = [[3, 6, 7], [4, 9, 9], [7, 6, 9]]
list_2 = [[6, 7, 2], [1, 5, 9], [8, 3, 4]]
print([x-y for x, y in zip(chain(*list_1), chain(*list_2)) if x-y])
# [-3, -1, 5, 3, 4, -1, 3, 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;
}
答案 2 :(得分:1)
以下代码对您有所帮助,
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);
答案 3 :(得分:0)
如果您只想使用LINQ解决此问题,以下内容将有所帮助 -
.box {
height: 300px;
}