C# Linq列表在C中的排名#
我有下面的名单,其中包括一个名单的名称和分数。我使用linq得到的分数是列表中所有人的分数之和:C# Linq列表在C中的排名#,c#,linq,observablecollection,C#,Linq,Observablecollection,我有下面的名单,其中包括一个名单的名称和分数。我使用linq得到的分数是列表中所有人的分数之和: Name Score Ed 5 John 6 Sara 7 Dean 3 Nora 4 因此,我能够对列表进行分组并计算总数,但现在我正试图根据分数对这些列表进行排序。因此,我试图获得以下列表: Rank Name Score 1 Sara 7 2 John 6 3 Ed 5 4 Nora 4 5 Dean
Name Score
Ed 5
John 6
Sara 7
Dean 3
Nora 4
因此,我能够对列表进行分组并计算总数,但现在我正试图根据分数对这些列表进行排序。因此,我试图获得以下列表:
Rank Name Score
1 Sara 7
2 John 6
3 Ed 5
4 Nora 4
5 Dean 3
但是我使用的linq代码似乎没有为我获得正确的排名
以下是我的代码,用于制作列表、求和和和排名:
public class Person
{
public int Rank { get; set; }
public string Name { get; private set; }
public int Score { get; set; }
public Person(int rank, string name, int score)
{
Rank = rank;
Name = name;
Score = score;
}
}
public ObservableCollection<Person> Persons { get; set; }
public MainWindow()
{
Persons = new ObservableCollection<Person>();
var data = lines.Select(line => {
var column = line.Split(',');
var name = column[0];
int score = int.Parse(column[1]);
int rank =0;
return new { name, score, rank };
});
var groupedData = data.OrderByDescending(x => x.score).GroupBy(p => p.name).Select((g, i) => new { name = g.Key, rank=i+1, score = g.Sum(p => p.score)});
var persons = groupedData.Select(p => new Person(p.rank, p.name, p.score));
foreach (var person in persons) {
Persons.Add(person);
}
datagrid.ItemsSource = Persons;
}
公共类人物
{
公共整数秩{get;set;}
公共字符串名称{get;private set;}
公共整数分数{get;set;}
公众人物(整数排名、字符串名称、整数分数)
{
秩=秩;
名称=名称;
分数=分数;
}
}
公共可观察集合人员{get;set;}
公共主窗口()
{
人员=新的可观察集合();
变量数据=行。选择(行=>{
var column=line.Split(',');
变量名称=列[0];
int score=int.Parse(列[1]);
int秩=0;
返回新的{name,score,rank};
});
var groupedData=data.OrderByDescending(x=>x.score).GroupBy(p=>p.name).Select((g,i)=>new{name=g.Key,rank=i+1,score=g.Sum(p=>p.score)});
变量persons=groupedData.Select(p=>newpersons(p.rank,p.name,p.score));
foreach(var个人对个人){
人。添加(人);
}
datagrid.ItemsSource=个人;
}
我只是想知道如何在linq中包含正确的等级。您必须
按降序排列分组数据(具有总分),而不是包含未求和的单个分数的原始数据
var persons = groupedData.Select(p => new Person(p.rank, p.name, p.score)).OrderByDescending(x => x.Score);
编辑:(将正确的排名放入Person.rank
)
您必须按降序排列groupedData
(具有总分),而不是包含未求和的单个分数的原始数据
var persons = groupedData.Select(p => new Person(p.rank, p.name, p.score)).OrderByDescending(x => x.Score);
编辑:(将正确的排名放入Person.rank
)
不久前我问了一个类似的问题。我的问题是,如果人们有相同的分数,它将分配错误的排名的人。根据您当前的代码,如果John的分数也为7,他将被排在第2位,因为您按分数排序,并且仅使用其在列表中的位置,而他实际上与第1位并列
这是我的问题和解决方案:不久前我问了一个类似的问题。我的问题是,如果人们有相同的分数,它将分配错误的排名的人。根据您当前的代码,如果John的分数也为7,他将被排在第2位,因为您按分数排序,并且仅使用其在列表中的位置,而他实际上与第1位并列
这是我的问题和解决方案:一个扩展方法如何进行排名:
public static IEnumerable<TResult> SelectRank<TSource, TValue, TResult>(this IEnumerable<TSource> source,
Func<TSource, TValue> valueSelector,
Func<TSource, int, TResult> selector)
where TValue : struct
{
TValue? previousValue = default(TValue?);
var count = 0;
var rank = 0;
foreach (var item in source)
{
count++;
var value = valueSelector(item);
if (!value.Equals(previousValue))
{
rank = count;
previousValue = value;
}
yield return selector(item, rank);
}
}
公共静态IEnumerable SelectRank(此IEnumerable源,
Func值选择器,
Func选择器)
其中TValue:struct
{
TValue?previousValue=默认值(TValue?);
var计数=0;
var秩=0;
foreach(源中的var项)
{
计数++;
var值=值选择器(项目);
如果(!value.Equals(previousValue))
{
排名=计数;
前一个值=值;
}
收益率返回选择器(项目、等级);
}
}
用法profiles.SelectRank(x=>x.Score,(x,r)=>new{x.Name,Rank=r})
。此方法只对源代码执行1次迭代。我确实建议使用排序的源
参数。扩展方法如何进行排序:
public static IEnumerable<TResult> SelectRank<TSource, TValue, TResult>(this IEnumerable<TSource> source,
Func<TSource, TValue> valueSelector,
Func<TSource, int, TResult> selector)
where TValue : struct
{
TValue? previousValue = default(TValue?);
var count = 0;
var rank = 0;
foreach (var item in source)
{
count++;
var value = valueSelector(item);
if (!value.Equals(previousValue))
{
rank = count;
previousValue = value;
}
yield return selector(item, rank);
}
}
公共静态IEnumerable SelectRank(此IEnumerable源,
Func值选择器,
Func选择器)
其中TValue:struct
{
TValue?previousValue=默认值(TValue?);
var计数=0;
var秩=0;
foreach(源中的var项)
{
计数++;
var值=值选择器(项目);
如果(!value.Equals(previousValue))
{
排名=计数;
前一个值=值;
}
收益率返回选择器(项目、等级);
}
}
用法profiles.SelectRank(x=>x.Score,(x,r)=>new{x.Name,Rank=r})
。此方法只对源代码执行1次迭代。我建议使用排序的源
参数。在此处添加代码以供完成,例如:
var entriesByPoints = tournament.Entries.GroupBy(g=>g.Picks.Sum(s=>s.TournamentContestant.TotalScoreTargetAllocatedPoints)).Select((group)=> new {
Points = group.Key,
Entries = group.ToList()
});
var entriesByRankWithPoints = entriesByPoints.OrderByDescending(ob=>ob.Points).Select((p,i) => new {
Rank = 1 + (entriesByPoints.Where(w=>w.Points > p.Points).Sum(s=>s.Entries.Count())),
Points = p.Points,
Entries = p.Entries
});
结果:
在此处添加代码以完成比赛示例:
var entriesByPoints = tournament.Entries.GroupBy(g=>g.Picks.Sum(s=>s.TournamentContestant.TotalScoreTargetAllocatedPoints)).Select((group)=> new {
Points = group.Key,
Entries = group.ToList()
});
var entriesByRankWithPoints = entriesByPoints.OrderByDescending(ob=>ob.Points).Select((p,i) => new {
Rank = 1 + (entriesByPoints.Where(w=>w.Points > p.Points).Sum(s=>s.Entries.Count())),
Points = p.Points,
Entries = p.Entries
});
结果:
您好,谢谢您的回复。我尝试了你提出的解决方案,但仍然没有得到正确的排名:排名编码在列表位置,我将更新答案,在Person.rank
Perfect中提供它!现在我需要弄清楚如何为那些得分相同的人确定排名。非常感谢:)我会按分数分组,按分数排序,然后根据每个GroupGreeting中的元素数进行聚合来创建排名。谢谢你的回复。我尝试了你提出的解决方案,但仍然没有得到正确的排名:排名编码在列表位置,我将更新答案,在Person.rank
Perfect中提供它!现在我需要弄清楚如何为那些得分相同的人确定排名。非常感谢:)我会按分数分组,按分数排序,然后通过每个组中元素的计数进行聚合来创建排名谢谢您的回复。您能解释一下解决方案吗?因为我不明白它的实现是如何解决这个问题的:)谢谢您的回复。您能解释一下解决方案吗,因为我不明白它的实现是如何解决这个问题的:)