LINQ:不同的价值观

bal*_*int 132 linq distinct

我从XML中设置了以下项目:

id           category

5            1
5            3
5            4
5            3
5            3
Run Code Online (Sandbox Code Playgroud)

我需要这些项目的清单:

5            1
5            3
5            4
Run Code Online (Sandbox Code Playgroud)

如何在LINQ中区分Category AND Id?

Jon*_*eet 213

您是否想要通过多个字段区分?如果是这样,只需使用匿名类型和Distinct运算符,它应该没问题:

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

如果您正在尝试获取"更大"类型的一组不同的值,但只查看不同方面的某些属性子集,则可能需要DistinctByMoreLINQ中实现DistinctBy.cs:

 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;
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)

(如果您null作为比较器传入,它将使用键类型的默认比较器.)


Stu*_*Stu 33

只需使用Distinct()您自己的比较器.

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


Jam*_*der 26

除了Jon Skeet的答案之外,您还可以使用group by表达式来获取每个组迭代的唯一组和计数:

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() };
Run Code Online (Sandbox Code Playgroud)

  • 您写了“除Jon Skeet的答案外”……我不知道这样的事情是否可能。;) (2认同)

Ric*_*y G 12

对于任何仍在寻找的人; 这是实现自定义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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后,您可以为linq Distinct创建一个可以接受lambda的扩展

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

用法:

var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);
Run Code Online (Sandbox Code Playgroud)


Oll*_*son 8

我的答案有点迟了,但是如果你想要整个元素,你可能想要这样做,而不仅仅是想要分组的值:

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

这将通过选择为您提供与您的组匹配的第一个完整元素,就像Jon Skeets使用DistinctBy的第二个示例,但没有实现IEqualityComparer比较器.DistinctBy很可能会更快,但如果性能不是问题,上面的解决方案将涉及更少的代码.