You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于含IngredientsIds的所有属性实现Recipe类的DistinctBy去重

解决Recipe类的去重问题

你的代码无法正确去重,核心原因有两个:

  • 匿名类中的IEnumerable<int>类型(也就是IngredientsIds)默认用引用比较,而非内容比较——哪怕两个集合的元素完全一致,只要是不同的集合实例,就会被判定为不同的键。
  • 你需要忽略IngredientsIds的顺序,只判断元素是否完全相同,这也不在默认的去重逻辑范围内。

下面给你两种可行的解决方案:

方案一:自定义相等比较器(更严谨)

创建一个实现IEqualityComparer<Recipe>的比较器类,逐一对比所有简单属性,再通过SetEquals判断IngredientsIds的元素是否一致(因为你说元素不会重复,SetEquals可以忽略顺序直接判断内容是否完全匹配)。

public class RecipeEqualityComparer : IEqualityComparer<Recipe>
{
    public bool Equals(Recipe x, Recipe y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        
        // 逐一对比所有简单类型属性
        if (x.Name != y.Name) return false;
        if (x.Cost != y.Cost) return false;
        // 这里补充你那10个其他简单属性的对比,比如:
        // if (x.PrepTime != y.PrepTime) return false;
        // ...
        
        // 对比IngredientsIds:转成HashSet后用SetEquals忽略顺序判断内容
        var xIngredients = x.IngredientsIds?.ToHashSet() ?? new HashSet<int>();
        var yIngredients = y.IngredientsIds?.ToHashSet() ?? new HashSet<int>();
        return xIngredients.SetEquals(yIngredients);
    }

    public int GetHashCode(Recipe obj)
    {
        if (obj == null) return 0;
        
        var hash = new HashCode();
        // 组合所有简单属性的哈希码
        hash.Add(obj.Name);
        hash.Add(obj.Cost);
        // 补充你那10个其他属性的哈希码:
        // hash.Add(obj.PrepTime);
        // ...
        
        // 组合IngredientsIds的哈希码:先排序再逐个添加,确保顺序不影响结果
        if (obj.IngredientsIds != null)
        {
            foreach (var id in obj.IngredientsIds.OrderBy(id => id))
            {
                hash.Add(id);
            }
        }
        
        return hash.ToHashCode();
    }
}

使用时直接把比较器传给Distinct方法:

var uniqueRecipes = recipes.Distinct(new RecipeEqualityComparer());

方案二:修改DistinctBy的键(更简洁)

把IngredientsIds转换成排序后的字符串,这样匿名类的键会基于内容判断相等,同时自动处理顺序问题。

var uniqueRecipes = recipes
    .DistinctBy(d => new
    {
        d.Name,
        d.Cost,
        // 这里补充你那10个其他简单属性
        // d.PrepTime,
        // ...
        // 将IngredientsIds排序后拼接成字符串,确保元素相同则键相同
        IngredientsKey = d.IngredientsIds != null 
            ? string.Join(",", d.IngredientsIds.OrderBy(id => id)) 
            : string.Empty
    });

这种方式适合简单场景,缺点是如果IngredientsIds的元素数量很大,拼接字符串可能有轻微的性能损耗,但大部分日常场景下完全够用。

内容的提问来源于stack exchange,提问作者asdgvx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 07:00:13