我正在使用LINQ对多个字段进行排序。但是如何确定列表中的两个或多个条目是否相等?也就是说,所有字段都是相等的,并且排序顺序不会因为相等而改变。
public List<SfpDb.ResultatViewRang> sortResMest(List<SfpDb.ResultatViewRang> resultat)
{
return resultat
.OrderBy(p => p.statdsq)
.ThenBy(p => p.statdns)
.ThenBy(p => p.statdnf)
.ThenByDescending(p => p.totsum)
.ThenByDescending(p => p.totOmskyting)
.ThenByDescending(p => p.totinnertreff)
.ThenByDescending(p => p.sumr10)
.ThenByDescending(p => p.sumr9)
.ThenByDescending(p => p.sumr8)
.ThenByDescending(p => p.sumr7)
.ThenByDescending(p => p.sumr6)
.ThenByDescending(p => p.sumr5)
.ThenByDescending(p => p.sumr4)
.ThenByDescending(p => p.sumr3)
.ThenByDescending(p => p.sumr2)
.ThenByDescending(p => p.sumr1)
.ThenBy(p => p.perTreffRangStr)
.ThenBy(p => p.enavn, strCompareNo)
.ThenBy(p => p.fnavn, strCompareNo)
.ToList<SfpDb.ResultatViewRang>();
}
内容来自保存比赛结果的数据库,并根据比赛规则进行排序。排序用于确定竞争对手获得的位置。
根据规则,如果一个或多个竞争者从竞争中获得相同的价值(p.totsum,p.totOmskyting,.....),他们就会获得相同的位置。例如:
吉姆哈里斯,580,25,32,.....
汤姆詹森,560,20,30,.....
3.让·约翰逊,523,23,26,.....
3. Roy Beeman,523,23,26,.....
5. Doug Wilson,520,23,26,.....
排序后我遇到的问题是,我不确定如何识别本例中位置3的两个人。
一般而言,具有以下类别:
public class MigrObject
{
public int first { get; set; }
public int second { get; set; }
public int third { get; set; }
}
将使用
进行排序.OrderByDescending(p => p.first)
.ThenByDescending(p => p.second)
.ThenByDescending(p => p.third)
有以下记录:(第一,第二,第三)
580,25,32
560,30,30
523,23,26
523,23,26
523,23,26
520,23,26
518,40,30
518,40,30
430,14,16
您如何识别相同的记录?处理完记录后,它应具有以下位置/顺序:
1:580,25,32
2:560,30,30
3:523,23,26
3:523,23,26
3:523,23,26
6:520,23,26
7:518,40,30
7:518,40,30
9:430,14,16
根据国际规则,参与者将按第一个字段中的值(第一个)进行排序。如果存在平局,则将比较第二列,因此我们对“秒”进行排序。如果仍然存在平局,则将比较第三列,因此我们对“第三”进行排序。如果仍有任何关系,运动员必须具有相同的排名,并且必须使用运动员的姓氏以拉丁字母顺序列出。
如果加工后的位置是1,2,3,3,3,6,7或1,2,3,3,3,4,5并不重要。 主要问题是在比较所有字段后知道是否有任何关系,以及涉及哪些记录。
我希望LINQ中有一些功能允许您在所有比较字段相等的情况下收到通知。
答案 0 :(得分:0)
请试试这个。 我已经过测试并且有效。
public class Program
{
public class TestData
{
public int First { get; set; }
public int Second { get; set; }
public int Third { get; set; }
public int Place { get; set; }
}
public static void Main(string[] args)
{
var data = new List<TestData>
{
new TestData {First = 580, Second = 25, Third = 32},
new TestData {First = 560, Second = 30, Third = 30},
new TestData {First = 523, Second = 23, Third = 26},
new TestData {First = 523, Second = 23, Third = 26},
new TestData {First = 523, Second = 23, Third = 26},
new TestData {First = 520, Second = 23, Third = 26},
new TestData {First = 518, Second = 40, Third = 30},
new TestData {First = 518, Second = 40, Third = 30},
new TestData {First = 430, Second = 14, Third = 16}
};
var sorted =
(from d in data
orderby d.First descending, d.Second descending, d.Third descending
group d by d.First.ToString() + d.Second + d.Third into gd
select gd.ToList())
.ToList();
var result = new List<TestData>();
var place = 1;
foreach (var sd in sorted)
{
sd.ForEach(p => p.Place = place);
result.AddRange(sd);
place += sd.Count;
}
}
}
答案 1 :(得分:-1)
尝试这样的事情:(为了简单起见,我使用的是MigrObject
示例)
Dictionary<MigrObject, int> orderedResult = new Dictionary<MigrObject, int>(); //reverse dictionary where int is the 'order' you want
foreach (var item in resultat) // assuming resultat is a List of MigrObject
{
int order = 1;
if(!orderedResult.Any(o => o.first == item.first && o.second == item.second && o.third == item.third)) // I don't use ContainsKey(item) because it may not work for custom defined classes as key
{
orderedResult.Add(item, order);
count++;
}
else
orderedResult.Add(item, order);
}
看起来可能很复杂,但这里有解释:
- 字典相反,因为我们可以为同一个键设置多个值,但没有相反的方法
- 从1开始,因为没有第0位(在你的例子中)
- 检查字典是否包含每个项目的记录:如果不是,请添加它并将计数增加1,如果是,则不增加计数(因此给出2个重复的相同顺序)
- 这假设resultat
列表已正确排序。
- 当你有很多要比较的字段时,这种方法可能会变得复杂,但如果你有更好的比较方法,你可以修改它。
终于你可以遍历字典,每个项目的“位置/顺序”都是它的值,你可以将它添加到一个数组,或者你想要的任何数据类型。 (除了词典,因为键必须是唯一的)
答案 2 :(得分:-1)
尝试这样做:
var scores = new [] { 580, 560, 523, 523, 523, 520, 518, 518, 430, };
var results =
scores
.OrderByDescending(x => x) // just in case scores not in order
.GroupBy(x => x)
.Aggregate(
new { Rank = 1, Results = new List<Tuple<int, int>>() },
(a, gx) =>
{
a.Results.AddRange(gx.Select(x => Tuple.Create(a.Rank, x)));
return new { Rank = a.Rank + gx.Count(), Results = a.Results };
})
.Results;
我得到以下结果:
您需要调整代码以适合您的输入。