2013-08-16 86 views
3

這可能是顯而易見的,但我無法繞過它。在LINQ中,如何爲每個ID選擇一個項目?

我有一個項目清單,例如:

BOB 5 
Brian 5 
Sam 6 
James 7 
Emily 8 
Sandra 8 
Michael 8 

這些都是在一個List<MyObject>

我想過濾列表所以每個ID只有1項,通過選擇第一個用唯一身份。

我應該結束了

BOB 5 
Sam 6 
James 7 
Emily 8 

我無法制定出一個乾淨的方式來做到這一點。有任何想法嗎?

+1

可能與。首先(組合GROUPBY)應該工作,但我無法制定它:( –

+0

你怎麼知道挑鮑勃布萊恩,而不是我的意思嗎? ,你說「冷杉噸「,但有什麼資格作爲第一?日期時間戳,字母順序... – SQLMason

+0

你見過這個:http://stackoverflow.com/questions/489258/linq-distinct-on-a-particular-property? –

回答

7

使用GroupByFirst方法組合:

var results = source.GroupBy(x => x.Id).Select(g => g.First()).ToList(); 

或者作爲基於語法的查詢:

var results = (from i in source 
       group i by i.Id into g 
       select g.First()).ToList(); 
+0

精靈,作品一種享受。謝謝!另一個用於工具集。 – NibblyPig

1

我認爲,正確的方法是實現IEquatable

然後使用.Distinct()

這裏是如何使用它的鏈接。這樣您可以更好地控制第一個項目的處理方式。

http://msdn.microsoft.com/en-us/library/bb348436.aspx

+1

這裏有一個關於如何重寫[IEquatable]的問題(http://stackoverflow.com/questions/3897672/linq-object-equality-and-how-to-properly-override-it?rq=1) – SQLMason

0

你需要一個更好的直觀方法,可以做「者皆不同」。

public static IEnumerable<TSource> Distinct<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) 
{ 
    var seen = new HashSet<TKey>(); 
    foreach(var x in source) 
    { 
     var key = keySelector(x); 
     if (seen.Add(key);) 
      yield return x; 
    } 
} 
+0

關於無關請注意,請不要[批准建議編輯](http://stackoverflow.com/review/suggested-edits/2763311)使用反引號強調,但拒絕或改進它們 - 請參閱[here](http://meta.gaming.stackexchange.com/q/7437/88)爲什麼 –

+0

當然,這很有道理 –

+0

感謝您的理解:) –

0

這應該是相當快:

int c = 0; 
var results = source.Where(i => 
{ 
    if (i.Id > c) 
    { 
     c = i.Id; 
     return true; 
    } 
    else 
     return false; 
}).ToList(); 
0

(可以說)以上的GroupBy /第一組合效率,但它需要ID(-1)的特殊空值,以及與同所有項目ID列表中的分組:

 int currentID = -1; 
     var unique = list.Where(x => 
     { 
      if (currentID != -1 && currentID == x.ID) 
       return false; 

      currentID = x.ID; 
      return true; 
     }); 
相關問題