比较2个对象列表

时间:2015-01-07 20:00:16

标签: c# list inheritance

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

我有一个植物类,其中包含一个带有名称和重量的构造函数。

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

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

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

我在水果中重载了==运算符,以便比较水果和蔬菜的名称以及它们是否具有相同的名称。我的问题是,当我尝试比较整个列表以找到重复时,我只是无法让代码工作。

这是我的一些代码 植物类

    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
    }

这里是veg

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....
    }

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

6 个答案:

答案 0 :(得分: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()函数。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

我使用LINQ,而不是(或除此之外)重载==运算符,去更多本地&#34; 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 完全相等的情况。也就是说,它们之间的顺序必须相同:如果两者都包含&#34;胡萝卜,西兰花,&#34;你会没事的,但如果是那个,那么另一个是#34; Broccoli,Carrot,&#34;这将返回false。

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

return fr.Intersect(ve);

答案 4 :(得分:1)

您真的不需要重载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;
}

答案 5 :(得分:0)

首先感谢所有人的投入,你们都帮助我更清楚地看到问题。 但是重载==运算符是我必须要做的事情。

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

通过嵌套forEach循环,我会针对每个水果列表项检查veg的每个列表项。

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中的方法时比较名称。即使植物具有不同的重量,它们也被认为是相同的。

再次感谢输入人员。