当前位置:  开发笔记 > 编程语言 > 正文

LINQ:不同的价值观

如何解决《LINQ:不同的价值观》经验,为你挑选了5个好方法。

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

id           category

5            1
5            3
5            4
5            3
5            3

我需要这些项目的清单:

5            1
5            3
5            4

如何在LINQ中区分Category AND Id?



1> Jon Skeet..:

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

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

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

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

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



2> Stu..:

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

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



3> James Alexan..:

除了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() };


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

4> Ricky G..:

对于任何仍在寻找的人; 这是实现自定义lambda比较器的另一种方法.

public class LambdaComparer : IEqualityComparer
    {
        private readonly Func _expression;

        public LambdaComparer(Func 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 Distinct创建一个可以接受lambda的扩展

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

用法:

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



5> Olle Johanss..:

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

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很可能会更快,但如果性能不是问题,上面的解决方案将涉及更少的代码.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有