比较 2 个对象列表

本文关键字:列表 对象 比较 | 更新日期: 2023-09-27 18:36:43

我的 c# 应用程序中有几个类。

我有一个带有构造函数的植物类,该构造函数采用名称和权重。

然后我有一个 Fruit 类,它继承植物并添加种子数属性。

此外,我还有一个从植物继承并添加 savoryLevel 属性的 Veg 类。

用户可以将水果和蔬菜添加到他们的列表中。

我在水果中重载了 == 运算符,以便它比较水果和蔬菜的名称,如果它们具有相同的名称,它会告诉您。我的问题是当我尝试比较整个列表以查找重复项时,我根本无法让代码工作。

这是我的一些代码植物类

    public string name;
    public string weight;
    public Plant(string name, string weight)
    {
        this.name = name;
        this.email = weight;
    }
    ....
    public static bool operator ==(Plant a, Plant b)
    {
        // If both are null, or both are same instance, return true.
        if (System.Object.ReferenceEquals(a, b))
        {
            return true;
        }
        // If one is null, but not both, return false.
        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }
        // Return true if the fields match:
        return a.name == b.name;
    }

然后是新的水果构造函数

 string seeds;
public fruit(string name, string weight, string seeds)
        : base(name, weight)
    {
      this.seeds
    }

这里是蔬菜

string savoryLevel;
public fruit(string name, string weight, string savouryLevel)
        : base(name, weight)
    {
      this.savoryLevel
    }

这是我比较 2 个实例的主要内容,这工作正常

  Fruit f = new Fruit("apple", "2", "5");
  Veg v = new Veg("carrot", "3", "7");
  if (f == v)
     { 
     Console.WriteLine("They are the same");
     }
      else{
     Console.WriteLine("They are different");
     }

这是棘手的部分,我需要遍历我的整个蔬菜和水果列表,看看是否有任何水果与蔬菜同名。

直接使用列表不起作用

    List<Fruit> fr = new List<Fruit>();
    List<Veg> ve = new List<Veg>();
    if(fr == ve){
    Console.....
    }
     else{
     Console....
    }

那么我如何让列表进行比较并打印出一些结果,说这些是相同的还是不一样的呢?非常感谢任何帮助,谢谢。请询问您是否想要更多信息。

比较 2 个对象列表

我认为您应该使用IEquatable<Plant>并将列表转换为List<Plant> SequenceEquals()

演示:

public class Plant : IEquatable<Plant>
{
    public string Name { get; set; }
    public string Weight { get; set; }
    public override bool Equals(object obj)
    {
        var other=obj as Plant;
        if(other!=null)
        {
            return Equals(other);
        }
        return false;
    }
    public bool Equals(Plant other)
    {
        Debug.WriteLine("Checking Equality Between {0} And {1}", Name, other.Name);
        return Name.Equals(other.Name);
    }
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}
public class Fruit : Plant
{
    public string Seeds { get; set; }
}
public class Veg : Plant
{
    public string SavoryLevel { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        List<Fruit> fruits=new List<Fruit>() { 
            new Fruit() { Name="apple", Weight = "2", Seeds="5" },
            new Fruit() { Name="banana", Weight="1", Seeds="30" }
        };
        List<Veg> veggies=new List<Veg>() {
            new Veg() { Name = "carrot", Weight="3", SavoryLevel="7" },
            new Veg() { Name = "potato", Weight="5", SavoryLevel="1" }
        };
        var equal=fruits.Cast<Plant>().SequenceEqual(veggies);
        var unique_fruits=fruits.Distinct();
    }
}

它产生输出

Checking Equality Between apple And carrot

然后相等比较结束(因为它是假的)。关键是它调用了适当的Equals()函数。

如果要比较同一索引中的项目Zip方法可能很有用:

bool result = fr.Zip(ve, (f,v) => new { f, v }).All(x => x.f == x.v);

Zip方法创建对应项对,然后将每对项放入匿名类型。All方法只是检查对中的所有项目是否相等。

如果你想按项目使用它,你可以这样做

foreach(var fruit in fr)
{
    if(ve.Any(x => x.Name == fruit.Name))
    {
        Console.Write(fruit.Name + " is in both lists");
    }
}
我会

使用 LINQ,而不是(或除了)重载==运算符,选择"更原生"的object.Equalsobject.GetHashCode

public override int GetHashCode()
{
    return this.name.GetHashCode();
}
public override bool Equals(object b)
{
    Plant bPlant = b as Plant;
    // If one is null, but not both, return false.
    if (bPlant == null)
    {
        return false;
    }
    // Return true if the fields match:
    return this.name == b.name;
}

然后可以使用 LINQ:

return fr.SequenceEquals(ve);

当然,请注意,顾名思义,这仅在frve完全相等时才有效。也就是说,它们之间的顺序必须相同:如果两者都包含"胡萝卜,西兰花",你会没问题,但如果一个是那个,另一个是"西兰花,胡萝卜",这将返回 false。

除非我误解了,事实上你想要交叉点,不知道它们是平等的,在这种情况下:

return fr.Intersect(ve);

你真的不需要重载Equals方法来找出是否有不同的东西。如果您正在寻找不同的行为,而不是不同的结果,则应使用 Equals 方法重载。

既然这种情况比较了两个不同类中的两个字符串成员,为什么不直接使用 LINQ 来比较具有相同数据类型的成员本身呢?

using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
    public static void Main()
    {
        List<Fruit> f = new List<Fruit>();
        Fruit fTemp = new Fruit() { name = "Kiwi" };
        f.Add(fTemp);
        fTemp = new Fruit() { name = "Tomato" };
        f.Add(fTemp);
        List<Veg> v = new List<Veg>();
        Veg vTemp = new Veg() { name = "Tomato" };
        v.Add(vTemp);
        List<Veg> vDuplicates = v.Where(vegToCompare=>f.Any(fruitToCompare=>fruitToCompare.name.Equals(vegToCompare.name))).ToList();
        vDuplicates.ForEach(a=>Console.WriteLine(a.name));
        Console.WriteLine("Number of Duplicates Found: " + vDuplicates.Count);
    }
}
public class Fruit
{
    public string name;
}
public class Veg
{
    public string name;
}
首先感谢

大家的投入,你们都帮助我更清楚地看到了问题。但是重载 == 运算符是我作为要求的一部分必须做的事情。

但是,我找到了一种相对简单的方法来比较使用我添加到 Plant 类的重载 == 运算符的 2 个列表

通过嵌套一个forEach循环,我根据每个水果列表项检查蔬菜的每个列表项。

public void Compare(List<Fruit> frList, List<Veg> vList)
    {
        foreach (Fruit f in frList)
        {
            foreach (Veg v in vList)
            {
                if (f == v)
                { 
                   //some functionality
                }else{
                  //some other funtionality
                }
            }
        }
    }

这仍然使用工厂中的重载 == 运算符,并且只会在我在 main 中调用方法时比较名称,即即使植物具有不同的权重,它们也会被认为是相同的。

再次感谢您的输入。