2009-06-15 83 views
114

我有以下的項目從一個XML設置:LINQ:不同的值

id   category 

5   1 
5   3 
5   4 
5   3 
5   3 

我需要這些物品的一個獨特的列表:

5   1 
5   3 
5   4 

我如何不同的分類和ID太LINQ?

回答

185

您是否想通過一個以上的領域來區分?如果是這樣,只需使用匿名類型和DISTINCT運算符,它應該是好的:

var query = doc.Elements("whatever") 
       .Select(element => new { 
          id = (int) element.Attribute("id"), 
          category = (int) element.Attribute("cat") }) 
       .Distinct(); 

如果你想獲得一組不同的一個「大」類型的值,而只是看一些子集在清晰度方面的屬性,你可能想DistinctByMoreLINQ實施了DistinctBy.cs:(如果你在null通過作爲比較器,它將使用的密鑰類型默認的比較)

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    IEqualityComparer<TKey> comparer) 
{ 
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer); 
    foreach (TSource element in source) 
    { 
     if (knownKeys.Add(keySelector(element))) 
     { 
      yield return element; 
     } 
    } 
} 

+0

哦,這樣的「大類型」你可能意味着我仍然需要結果中的所有屬性,即使我只想比較幾個屬性以確定清晰度? – 2016-09-20 14:31:06

+0

@ TheRedPea:是的,確切的。 – 2016-09-20 14:46:42

22

除了喬恩斯基特的回答,您還可以使用通過表達式來獲得獨特的羣體一起瓦特/每個組重複計數:

var query = from e in doc.Elements("whatever") 
      group e by new { id = e.Key, val = e.Value } into g 
      select new { id = g.Key.id, val = g.Key.val, count = g.Count() }; 
3
// First Get DataTable as dt 
// DataRowComparer Compare columns numbers in each row & data in each row 

IEnumerable<DataRow> Distinct = dt.AsEnumerable().Distinct(DataRowComparer.Default); 

foreach (DataRow row in Distinct) 
{ 
    Console.WriteLine("{0,-15} {1,-15}", 
     row.Field<int>(0), 
     row.Field<string>(1)); 
} 
7

我答案有點遲,但如果你想要整個元素,你可能想要這樣做,而不僅僅是你想要分組的值:

var query = doc.Elements("whatever") 
       .GroupBy(element => new { 
          id = (int) element.Attribute("id"), 
          category = (int) element.Attribute("cat") }) 
       .Select(e => e.First()); 

這會給你第一個整體元素通過選擇匹配你的組,很像Jon Skeets第二個使用DistinctBy的例子,但是沒有實現IEqualityComparer比較器。 DistinctBy很可能會更快,但如果性能不成問題,上面的解決方案將涉及更少的代碼。

11

對於任何一個仍在尋找;這是另一種實現自定義lambda比較器的方式。

public class LambdaComparer<T> : IEqualityComparer<T> 
    { 
     private readonly Func<T, T, bool> _expression; 

     public LambdaComparer(Func<T, T, bool> lambda) 
     { 
      _expression = lambda; 
     } 

     public bool Equals(T x, T y) 
     { 
      return _expression(x, y); 
     } 

     public int GetHashCode(T obj) 
     { 
      /* 
      If you just return 0 for the hash the Equals comparer will kick in. 
      The underlying evaluation checks the hash and then short circuits the evaluation if it is false. 
      Otherwise, it checks the Equals. If you force the hash to be true (by assuming 0 for both objects), 
      you will always fall through to the Equals check which is what we are always going for. 
      */ 
      return 0; 
     } 
    } 

您可以創建爲LINQ鮮明,可以採取在拉姆達的

public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, T, bool> lambda) 
     { 
      return list.Distinct(new LambdaComparer<T>(lambda)); 
     } 

用途的擴展:

var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);