Skip to main content
 首页 » 编程设计

c#之使用 LINQ GroupBy 获取忽略属性的唯一集合

2024年01月22日26findumars

使用 Rules 集合,我试图创建另一个 Rules 集合,忽略 Site 属性并创建一个唯一列表。

public class Rule 
{ 
    public int TestId { get; set; } 
    public string File { get; set; } 
    public string Site { get; set; } 
    public string[] Columns { get; set; } 
} 

所以如果我的收藏有如下值:

var rules = new List<Rule> 
{ 
    new Rule { TestId = 1, File = "Foo", Site = "SiteA", Columns = new string[] { "ColA", "ColB" }}, 
    new Rule { TestId = 1, File = "Foo", Site = "SiteB", Columns = new string[] { "ColA", "ColB" }} 
}; 

我要的是最终结果

var uniqueRules = new List<Rule> 
{ 
    new Rule { TestId = 1, File = "Foo", Site = null, Columns = new string[] { "ColA", "ColB" }} 
}; 

尝试了如下所示的各种组合后,我仍然得到 2 个结果,如何才能达到预期的结果?

var uniqueRules = rules 
    .GroupBy(r => new { r.TestId, r.File, r.Columns }) 
    .Select(g => g.Key) 
    .Distinct() 
    .ToList(); 

请您参考如下方法:

问题是 string[]没有覆盖 Equals和 GetHashCode ,这就是为什么只在 r.Columns 比较引用文献的原因.您需要提供自定义 IEqualityComparer<T> :

public class RuleComparer : IEqualityComparer<Rule> 
{ 
    public bool Equals(Rule x, Rule y) 
    { 
        if (object.ReferenceEquals(x, y)) return true; 
        if (x == null || y == null) return false; 
        if(!(x.TestId == y.TestId && x.File == y.File)) return false; 
        return x.Columns.SequenceEqual(y.Columns); 
    } 
 
    // from: https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode 
    public int GetHashCode(Rule obj) 
    { 
        unchecked 
        { 
            int hash = 17; 
            hash = hash * 23 + obj.TestId.GetHashCode(); 
            hash = hash * 23 + (obj.File?.GetHashCode() ?? 0); 
            foreach(string s in obj.Columns) 
                hash = hash * 23 + (s?.GetHashCode() ?? 0); 
            return hash; 
        } 
    } 
} 

现在 LINQ 查询变得很简单:

List<Rule> uniqueRules = rules.Distinct(new RuleComparer()).ToList();