LINQ:不同值

72qzrwbm  于 2023-02-06  发布在  其他
关注(0)|答案(8)|浏览(143)

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

id           category

5            1
5            3
5            4
5            3
5            3

我需要一个明确的清单这些项目:

5            1
5            3
5            4

在LINQ中如何区分类别和Id?

r6l8ljro

r6l8ljro1#

您是否尝试通过多个字段区分?如果是这样,只需使用匿名类型和Distinct操作符,就可以了:

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

如果您试图获取“较大”类型的不同值集,但只查看不同属性的某些子集,您可能希望DistinctByDistinctBy.cs中实现为MoreLINQ

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

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

23c0lvtd

23c0lvtd2#

只需将Distinct()与您自己的比较器一起使用。
http://msdn.microsoft.com/en-us/library/bb338049.aspx

bxjv4tth

bxjv4tth3#

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

o75abkj44#

任何一个仍然在寻找;这是实现自定义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 Distinct创建一个扩展,它可以接受lambda

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);
kqhtkvqz

kqhtkvqz5#

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

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

lymnna71

lymnna716#

// 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)); 
}
46scxncf

46scxncf7#

因为我们讨论的是每个元素恰好出现一次,所以“集合”对我来说更有意义。
已实现类和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;
        }
    }

现在

List<Product> originalList = new List<Product> {new Product(1, "ad"), new Product(1, "ad")};
var setList = new HashSet<Product>(originalList, new ProductCompare()).ToList();

setList将具有唯一元素
我在处理返回set-difference的.Except()时想到了这一点

pod7payv

pod7payv8#

由于可以使用来自框架本身的.NET 6 DistinctBy,因此可以使用以下代码(利用值元组):

var query = doc.Elements("whatever")
   .DistinctBy(e => ((int) e.Attribute("id"), (int) e.Attribute("cat")))

相关问题