比较 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....
}
那么我如何让列表进行比较并打印出一些结果,说这些是相同的还是不一样的呢?非常感谢任何帮助,谢谢。请询问您是否想要更多信息。
我认为您应该使用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.Equals
并object.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);
当然,请注意,顾名思义,这仅在fr
和ve
完全相等时才有效。也就是说,它们之间的顺序必须相同:如果两者都包含"胡萝卜,西兰花",你会没问题,但如果一个是那个,另一个是"西兰花,胡萝卜",这将返回 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 中调用方法时比较名称,即即使植物具有不同的权重,它们也会被认为是相同的。
再次感谢您的输入。