2016-09-19 82 views
-2

我使用LINQ排序多個字段。但是,如何確定列表中的兩個或多個條目是否相等?也就是說,所有的字段都是平等的,排序順序不會因爲平等而改變。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,.....),則它們獲得相同的位置。例如:
1.吉姆哈里斯,580,25,32,.....
2.湯姆詹森,560,20,30,.....
3.讓·約翰遜,523,23,26 ,.....
羅伊比曼,523,23,26,......
5道格·威爾遜,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,4,4並不重要。主要問題是在比較所有字段以及涉及哪些記錄之後知道是否還有任何關係。

我希望LINQ中有一些功能可以在所有比較字段相同時通知您。

+1

您可以使用'Distinct'或'GroupBy'方法。 – Valentin

+0

_「所有字段都是平等的,排序順序不會因爲平等而改變」_ - 爲什麼你在意?你打算如何使用平等?請提供一個很好的[mcve],清楚地表明你正在嘗試做什麼。請準確而具體地解釋代碼的作用以及您希望它做什麼。 –

+0

嘗試檢查這個http://stackoverflow.com/q/312024/3956100確定你可以更改linq中的IComparer來滿足你的需求。 – Niklas

回答

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; 
      } 
     } 
    } 
+0

一個小問題 - 如果數字是「{52,32,326}」和'{523,23,26}','d.First.ToString()+ d.Second + d.Third'將失敗。你也許應該放入一個分隔線。像'$「{d.First}:{d.Second}:{d.Third}」''。 – Enigmativity

-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); 
} 

它可能看起來複雜,但這裏的解釋是:

-The字典逆轉,因爲我們可以有對於同一個密鑰,但各地

1,因爲沒有零的地方沒有其他的方式 - 啓動順序多個值(在你的例子)

- 檢查字典是否包含每個項目的記錄:如果否,則將其加1並遞增計數,如果是,則不遞增計數(因此給出2個重複的相同順序)

- resultat列表排序正確。

- 當您需要比較大量字段時,此方法可能會變得複雜,但如果您有更好的比較方法,則可以對其進行修改。

終於你可以遍歷字典,每個項目的「位置/順序」是它的值,你可以將它添加到一個數組或者你想要的任何數據類型。 (除了因爲鍵字典必須是唯一的

+0

感謝您的反饋。你知道你的不編譯,你不能使用'MigrObject'作爲字典的關鍵嗎? – Enigmativity

+0

謝謝。我會研究這一點。如果我必須遍歷列表,這可能工作。 –

-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; 

我得到以下結果:

result

您將需要調整代碼以適合您的輸入。

+0

如果低調選民會迴應,我很想知道我做錯了什麼? – Enigmativity

+0

我相信問題海報會低估他不喜歡的答案(你的作品,雖然方式更復雜,我的答案也是如此)。 –

+0

@Enigmativity:你的工作。你可能需要檢查它的性能。 –