LINQ:不同的值

LINQ:不同的值,linq,distinct,Linq,Distinct,我从XML中设置了以下项: id category 5 1 5 3 5 4 5 3 5 3 我需要这些项目的明确列表: 5 1 5 3 5 4 在LINQ中如何区分Category和Id?您是否试图通过多个字段来区分?如果是这样,只需使用匿名类型和Distinct运算符即可: var query

我从XML中设置了以下项:

id           category

5            1
5            3
5            4
5            3
5            3
我需要这些项目的明确列表:

5            1
5            3
5            4

在LINQ中如何区分Category和Id?

您是否试图通过多个字段来区分?如果是这样,只需使用匿名类型和Distinct运算符即可:

var query = doc.Elements("whatever")
               .Select(element => new {
                             id = (int) element.Attribute("id"),
                             category = (int) element.Attribute("cat") })
               .Distinct();
如果您试图获取一组“较大”类型的不同值,但仅查看差异性方面的某些属性子集,则可能需要
DistinctBy
,如中所实现:

公共静态IEnumerable DistinctBy(
这是一个数不清的来源,
Func键选择器,
IEqualityComparer(比较器)
{
HashSet knownKeys=新的HashSet(比较器);
foreach(源中的TSource元素)
{
if(knownKeys.Add(键选择器(元素)))
{
收益-收益要素;
}
}
}

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

只需将
Distinct()
与您自己的比较器一起使用即可

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;
        }
    }

除了Jon Skeet的答案外,您还可以使用group by表达式获得每个组迭代的w/a计数沿线的唯一组:

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() };
//首先获取数据表作为dt
//DataRowComparer比较每行中的列数和每行中的数据
IEnumerable Distinct=dt.AsEnumerable().Distinct(DataRowComparer.Default);
foreach(数据行在不同的位置)
{
Console.WriteLine({0,-15}{1,-15}),
第行字段(0),
行。字段(1));
}

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

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 comparer comparer。DistinctBy很可能会更快,但如果性能不是问题,上述解决方案将涉及更少的代码;下面是实现自定义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;
        }
    }

因为我们谈论的是每个元素都只有一次,所以“集合”对我来说更有意义

实现了类和IEqualityComparer的示例:

 public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public Product(int x, string y)
        {
            Id = x;
            Name = y;
        }
    }

    public class ProductCompare : IEqualityComparer<Product>
    {
        public bool Equals(Product x, Product y)
        {  //Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(x, y)) return true;

            //Check whether any of the compared objects is null.
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;

            //Check whether the products' properties are equal.
            return x.Id == y.Id && x.Name == y.Name;
        }
        public int GetHashCode(Product product)
        {
            //Check whether the object is null
            if (Object.ReferenceEquals(product, null)) return 0;

            //Get hash code for the Name field if it is not null.
            int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();

            //Get hash code for the Code field.
            int hashProductCode = product.Id.GetHashCode();

            //Calculate the hash code for the product.
            return hashProductName ^ hashProductCode;
        }
    }
公共类产品
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共产品(整数x,字符串y)
{
Id=x;
Name=y;
}
}
公共类产品比较:IEqualityComparer
{
公共布尔等于(乘积x,乘积y)
{//检查比较的对象是否引用相同的数据。
if(Object.ReferenceEquals(x,y))返回true;
//检查是否有任何比较对象为空。
if(Object.ReferenceEquals(x,null)| | Object.ReferenceEquals(y,null))
返回false;
//检查产品的属性是否相等。
返回x.Id==y.Id&&x.Name==y.Name;
}
public int GetHashCode(产品)
{
//检查对象是否为空
if(Object.ReferenceEquals(product,null))返回0;
//如果名称字段不为null,则获取其哈希代码。
int-hashProductName=product.Name==null?0:product.Name.GetHashCode();
//获取代码字段的哈希代码。
int hashProductCode=product.Id.GetHashCode();
//计算产品的哈希代码。
返回hashProductName^hashProductCode;
}
}
现在

List originalList=新列表{新产品(1,“广告”)、新产品(1,“广告”)};
var setList=newhashset(originalList,newproductcompare()).ToList();
setList
将具有唯一的元素


我在处理
时想到了这一点。除了()
它返回一个集差

哦,所以“较大类型”可能意味着我仍然需要结果中的所有属性,即使我只想比较几个属性以确定其差异性?@TheRedPea:是的,没错。查看参考源,Distinct使用哈希集存储它已经生成的元素。始终返回相同的哈希代码意味着每次都要检查以前返回的每个元素。一个更健壮的散列代码会加快速度,因为它只会与同一散列桶中的元素进行比较。零是一个合理的默认值,但它可能值得为哈希代码支持第二个lambda。这一点很好!当我有时间的时候我会尝试编辑,如果你现在正在这个领域工作,请随意编辑你写的“除了Jon Skeet的答案”。。。我不知道这样的事情是否可能发生
   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);
 public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public Product(int x, string y)
        {
            Id = x;
            Name = y;
        }
    }

    public class ProductCompare : IEqualityComparer<Product>
    {
        public bool Equals(Product x, Product y)
        {  //Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(x, y)) return true;

            //Check whether any of the compared objects is null.
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;

            //Check whether the products' properties are equal.
            return x.Id == y.Id && x.Name == y.Name;
        }
        public int GetHashCode(Product product)
        {
            //Check whether the object is null
            if (Object.ReferenceEquals(product, null)) return 0;

            //Get hash code for the Name field if it is not null.
            int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();

            //Get hash code for the Code field.
            int hashProductCode = product.Id.GetHashCode();

            //Calculate the hash code for the product.
            return hashProductName ^ hashProductCode;
        }
    }
List<Product> originalList = new List<Product> {new Product(1, "ad"), new Product(1, "ad")};
var setList = new HashSet<Product>(originalList, new ProductCompare()).ToList();