2009-06-15 41 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);