如何在多个字段中使用LINQ Distinct()

Cic*_*ami 62 c# linq distinct

我有从数据库派生的以下EF类(简化)

class Product
{ 
     public string ProductId;
     public string ProductName;
     public string CategoryId;
     public string CategoryName;
}
Run Code Online (Sandbox Code Playgroud)

ProductId是表的主键.

对于DB设计者做出的糟糕的设计决策(我无法修改它),我有CategoryIdCategoryName在这个表中.

我需要一个DropDownList的使用(不同)CategoryId价值,并CategoryName文本.因此我应用了以下代码:

product.Select(m => new {m.CategoryId, m.CategoryName}).Distinct();
Run Code Online (Sandbox Code Playgroud)

从逻辑上讲,它应该使用CategoryIdCategoryName作为属性创建一个匿名对象.在Distinct()保证有没有重复对(CategoryId,CategoryName).

但实际上它不起作用.据我所知,Distinct()当集合中只有一个字段时,它就会忽略它们......这是正确的吗?有没有解决方法?谢谢!

UPDATE

对不起product是:

List<Product> product = new List<Product>();
Run Code Online (Sandbox Code Playgroud)

我找到了另一种获得相同结果的方法Distinct():

product.GroupBy(d => new {d.CategoryId, d.CategoryName}) 
       .Select(m => new {m.Key.CategoryId, m.Key.CategoryName})
Run Code Online (Sandbox Code Playgroud)

Tim*_*ter 48

我假设您在列表中使用与方法调用类似的区别.您需要将查询结果用作DropDownList的数据源,例如通过实现它ToList.

var distinctCategories = product
                        .Select(m => new {m.CategoryId, m.CategoryName})
                        .Distinct()
                        .ToList();
DropDownList1.DataSource     = distinctCategories;
DropDownList1.DataTextField  = "CategoryName";
DropDownList1.DataValueField = "CategoryId";
Run Code Online (Sandbox Code Playgroud)

  • @CiccioMiami upvoters,确保您仅将此答案应用于匿名类型。类型化的类可能需要像 [this one](http://stackoverflow.com/a/43010363/538763) 这样的委托。 (2认同)

som*_*men 22

添加了.NET 6及更高版本的更新:DistinctBy

myQueryable.DistinctBy(c => new { c.KeyA, c.KeyB});
Run Code Online (Sandbox Code Playgroud)

https://learn.microsoft.com/en-us/dotnet/api/system.linq.queryable.distinctby?view=net-6.0

(对于IQueryableIEnumerable


seh*_*ehe 11

Distinct()保证没有重复对(CategoryId,CategoryName).

- 确切地说

匿名类型'神奇'的实现EqualsGetHashcode

我在某处假设另一个错误.区分大小写?可变课程?不可比较的领域?


Mic*_*mel 5

Key在您的选择中使用关键字将起作用,如下所示。

product.Select(m => new {Key m.CategoryId, Key m.CategoryName}).Distinct();

我意识到这是提出了一个旧线程,但认为它可能对某些人有所帮助。在使用 .NET 时,我通常在 VB.NET 中编码,因此Key可能会以不同的方式转换为 C#。

  • 为了对 VB.Net 中的多个字段进行区分,必须对匿名类型中的每个属性使用“Key”关键字。(否则,用于比较的哈希码将无法正确计算)在 C# 中,没有“Key”关键字 - 匿名类型中的所有属性都自动成为 Key 字段。 (5认同)

Nod*_*.JS 5

这是我的解决方案,它支持不同类型的 keySelectors:

public static IEnumerable<TSource> DistinctBy<TSource>(this IEnumerable<TSource> source, params Func<TSource, object>[] keySelectors)
{
    // initialize the table
    var seenKeysTable = keySelectors.ToDictionary(x => x, x => new HashSet<object>());

    // loop through each element in source
    foreach (var element in source)
    {
        // initialize the flag to true
        var flag = true;

        // loop through each keySelector a
        foreach (var (keySelector, hashSet) in seenKeysTable)
        {                    
            // if all conditions are true
            flag = flag && hashSet.Add(keySelector(element));
        }

        // if no duplicate key was added to table, then yield the list element
        if (flag)
        {
            yield return element;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用它:

list.DistinctBy(d => d.CategoryId, d => d.CategoryName)
Run Code Online (Sandbox Code Playgroud)