C# 在忽略关键字段的同时比较 2 个对象列表

C# comparing 2 lists of objects while ignoring the key field

我正在尝试比较 2 个对象列表是否相等,但我想忽略关键字段。 我该怎么做?

这是一个例子:

public class myProduct
{
    int ID {get; set;}
    int field1 {get; set;}
    int field2 {get; set;}
}

<List>myProduct greenProducts = new <List>myProduct();
<List>myProduct purpleProducts = new <List>myProduct();

greenProducts.Add(new myProduct { ID = 1, field1 = 5, field2 = 8});
greenProducts.Add(new myProduct { ID = 2, field1 = 9, field2 = 12});
greenProducts.Add(new myProduct { ID = 3, field1 = 7, field2 = 7});

purpleProducts.Add(new myProduct { ID = 8, field1 = 5, field2 = 8});
purpleProducts.Add(new myProduct { ID = 9, field1 = 9, field2 = 12});
purpleProducts.Add(new myProduct { ID = 10, field1 = 7, field2 = 7});

如果忽略关键字段(又名 ID 字段),这些列表完全相同。

所以我希望我的代码做这样的事情:

if (purpleProducts == greenProducts) //I WANT THE ID FIELD IGNORED FOR THE COMPARISON SO RESULT WITH ABOVE DATA WOULD BE TRUE
{
  //DO ACTION HERE
}
green.Zip(purple, (l,r)=>(l.field1 == r.field1) && (l.field2 == r.field2)).All(x=>x);

你可以遍历它。这是一个循环,可确保重复项的数量相同。

public class myProduct
{
    public int ID { get; set; }
    public int field1 { get; set; }
    public int field2 { get; set; }
}
List<myProduct> greenProducts = new List<myProduct>();
List<myProduct> purpleProducts = new List<myProduct>();

greenProducts.Add(new myProduct { ID = 1, field1 = 5, field2 = 8 });
greenProducts.Add(new myProduct { ID = 2, field1 = 9, field2 = 12 });
greenProducts.Add(new myProduct { ID = 3, field1 = 7, field2 = 7 });

purpleProducts.Add(new myProduct { ID = 8, field1 = 5, field2 = 8 });
purpleProducts.Add(new myProduct { ID = 9, field1 = 9, field2 = 12 });
purpleProducts.Add(new myProduct { ID = 10, field1 = 7, field2 = 7 });

var areEqual = true;
            
if (greenProducts.Count() != purpleProducts.Count()) areEqual = false;
if (areEqual)
{
    foreach (var item in greenProducts)
    {
        if(greenProducts.Where(g => g.field1 == item.field1 && g.field2 == item.field2).Count() != purpleProducts.Where(p => p.field1 == item.field1 && p.field2 == item.field2).Count())
        {
            areEqual = false;
            break;
        }
    }
}
if (areEqual)
{
    //DO ACTION HERE
}

因此,无需担心重复,元素可以按任何顺序排列

if(
  green.Select(x => new { x.field1, x.field2 })
    .ToHashSet()
    .SetEquals(purple.Select(x => new { x.field1, x.field2 }))
)

我们获取您的集合并将它们投射到您想要比较的字段的匿名类型。匿名类型内置了基于属性数据内容的相等逻辑,这使您不必在 class 中重写 Equals 和 GetHashCode(这是另一种选择)。通过将其中一个集合转换为哈希集,您可以询问它是否等于另一个集合。另一个集合不必是哈希集。

元组也可以实现类似的效果,它也内置了相等性检查

if(
  green.Select(x => (x.field1, x.field2))
    .ToHashSet()
    .SetEquals(purple.Select(x => (x.field1, x.field2)))
)

如果您重写 class 上的 Equals 和 GetHashCode,以便它们完全基于 field1 和 field2 声明相等,代码会变得更简单:

if(green.ToHashSet().SetEquals(purple))

覆盖的方法类似于:

override bool Equals(object other) => other is MyProduct x && this.field1 == x.field1 && this.field2 == x.field2;
override int GetHashCode() => HashCode.Combine(field1, field2); 

如果您创建集合 HashSet(上面也完成了覆盖)而不是 List,那么它们会自动删除重复数据,代码很简单

if(green.SetEquals(purple))