【问题标题】:How to compare two `List<MyObject1> with List<MyObject2>`?如何比较两个 `List<MyObject1> 和 List<MyObject2>`?
【发布时间】:2012-03-25 22:38:31
【问题描述】:

如何比较两个List&lt;MyObject1&gt;List&lt;MyObject2&gt;? 因此,如果一个 Value 具有不同的值,则应该可以对其进行检查。

(我知道我们可以使用foreach...但我想要LINQ解决方案/)

谢谢!

public sealed class MyObject1
{
    public string Name { get; set; }

    public string Value { set; get; }

    public Guid ID { get; set; }
}

public sealed class MyObject2
{
    public string Name { get; set; }

    public string Value { set; get; }

    public Guid ID { get; set; }
}

【问题讨论】:

  • 你想比较什么?列表还是列表中的对象?
  • @ChrisF 让我纠正我的问题请...完成
  • Peretz 枚举列表 A 中的每个对象,并将其与列表 B 中的每个对象进行比较。发布您尝试过的内容会让像我这样的人更愿意给您更大的提示。
  • 在这个问题上有一个类似的线程。 stackoverflow.com/questions/675699/… 很少有好的 linq 表达式。

标签: c# .net linq list


【解决方案1】:

this SO question 接受的答案建议使用Enumerable.SequenceEqual,记录在案的here

该方法需要两个IEnumerables 和一个IEqualityComparer。它并行迭代您的两个可枚举,并使用您提供的比较器逐个元素地检查相等性。

在 IEqualityComparer 实现中,您可能希望通过其 Id 属性来比较 MyObject 实例。

如果真的有两种对象类型,你可以做类似MyList1.Select(new MyObject2 {/*mapping goes here*/})或尝试使用AutoMapper

【讨论】:

  • 但 IEqualityComparer 当时只用于一种类型
  • 更新了我的答案来解决这个问题。
  • 我不喜欢这个解决方案,但是 +1 向我介绍了 AutoMapper
【解决方案2】:
public class myComparer: IEqualityComparer  
{
   public new bool Equals(object x, object y)
   {
      if (x is string )
         return  x ==   y;
      else if (x is Guid ) // maybe you want them to be equal if last char is equal. so you can do it here.
         return   x ==   y;
      else
         return EqualityComparer<object>.Default.Equals(x, y);
   }

   public int GetHashCode(object obj)
   {
      return EqualityComparer<object>.Default.GetHashCode(obj);
   }
}

现在

List<MyObject1 > lst1 = new MyObject1 <MyObject1 >(); 
//add items here...

List<MyObject2 > lst2 = new MyObject1 <MyObject2 >(); 
//add items here...

你可以把两种方式等同起来:

IStructuralEquatable equ = lst1 ;

  Console.WriteLine(equ.Equals(lst2 , EqualityComparer<object>.Default));

   or

   Console.WriteLine(equ.Equals(lst2 , new myComparer()));

【讨论】:

  • 样本中的 t1、t2 是什么意思?你能解释一下吗?
  • IMO,这不是一个好的解决方案。类型测试使其变得昂贵,并且硬塞一切对象以便您可以使用 IEqualityComparer 太棘手了一半。
  • @spender 只要他们不在继承模式下 - 你没有任何选择。如果他们有继承关系——我们可以做一些类型安全的事情。但OP没有提到它。 p.s.查看 MSDN 示例 - 与 myne 完全一样:msdn.microsoft.com/en-us/library/… 他们使用了 TUPLES。
  • 好的,很公平。 DV 已删除。在我看来仍然不是那么好。
【解决方案3】:

如果您不想(或不能)实现自己的IEqualityComparer,您可以压缩并比较字段:

list1.Count == list2.Count 
&& list1
    .Zip(list2, (i1,i2) => new{i1,i2})
    .All(x =>    x.i1.Name  == x.i2.Name
              && x.i1.Value == x.i2.Value
              && x.i1.ID    == x.i2.ID)

【讨论】:

  • ***rer 的整个想法是当您无法编辑课程时 - 所以您使用其他课程。你的句子不合逻辑(or can't) implement your own IEqualityComparer
  • list1.Zip(list2, (i1, i2) =&gt; i1.Name = i2.Name &amp;&amp; i1.Value == i2.Value &amp;&amp; i1.ID == i2.ID).All() 怎么样?
【解决方案4】:

你的类是一样的,所以我相信你想要做的是比较MyObject类型的两个对象列表:

public class MyObject
{
    public string Name { get; set; }

    public string Value { set; get; }

    public Guid ID { get; set; }
}

我发现最简单的方法是让MyObject 类实现IComparable 接口,而无需编写单独的IEqualityComparer。这在halfway down this page有详细解释,但这是你的类在实现接口后的样子:

public class MyObject :  IEquatable <MyObject >
{
    public string Name { get; set; }

    public string Value { set; get; }

    public Guid ID { get; set; }

    public bool Equals(MyObject other)
    {

    //Check whether the compared object is null. 
    if (Object.ReferenceEquals(other, null)) return false;

    //Check whether the compared object references the same data. 
    if (Object.ReferenceEquals(this, other)) return true;

    //Check whether the objects properties are equal. 
    return Name.Equals(other.Name) && Value.Equals(other.Value) && ID.Equals(other.ID);
    }

    public override int GetHashCode()
    {

    //Get hash code for the Name field if it is not null. 
    int hashName = Name == null ? 0 : Name.GetHashCode();

    //Get hash code for the Value field. 
    int hashCode = Value == null ? 0 : Value .GetHashCode();

    //Get hash code for the IDfield. 
    int hashID =  ID.GetHashCode();

    //Calculate the hash code for the entire object. 
    return hashName  ^ hashCode ^ hashId;
    }
}

一旦您的类具有Equals()GetHashCode() 方法,LINQ 的Except() 方法将自动工作:

List<MyObject> objects1 = { new MyObject{ Name = "apple", Value= "fruit", ID= 9 }, 
                           new MyObject{ Name = "orange", Value= "fruit", ID= 4 },
                            new MyObject{ Name = "lemon", Value= "fruit", ID= 12 } };

List<MyObject> objects2 = { new MyObject { Name = "apple", Value= "fruit", ID= 9 } };

List<MyObject> comparison = objects1.Except(objects2);

comparison 现在有橙子和柠檬,但没有苹果。我喜欢这个解决方案,因为最后一行的代码清晰易读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多