簡體   English   中英

比較兩個復雜對象列表

[英]Compare two list of complex object

我處於比較兩個復雜對象列表的情況,以查找插入的元素、修改的元素和刪除的元素:

小例子

  public class pippo
{
    public int fluido;
    public int abc;
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        List<pippo> lstact= new List<pippo>();
        List<pippo> lstprec = new List<pippo>();

        lstact.Add(new pippo { abc = 1, fluido = 1 });
        lstact.Add(new pippo { abc = 2, fluido = 1 });
        lstact.Add(new pippo { abc = 3, fluido = 1 });

        lstprec.Add(new pippo { abc = 1, fluido = 1 });
        lstprec.Add(new pippo { abc = 2, fluido = 1 });

        // compare two list for find item insert, deleted, modified


    }
}

要正確解決這個問題,您應該首先使對象具有可比性,然后使用內置列表函數和/或 LINQ 解決您的問題。

第一件事:對象比較的基礎知識

在 C# 中,每個類都從類“對象”派生。 “對象”為每個類提供了一種基本的比較方式,它說:當 im 是同一個實例時,(內存中的相同位置),那么 im 相等。

所以:通常情況下,當你比較兩個對象並且沒有定義其他任何東西時,C# 不會比較對象的內容(深度比較),但它會真正檢查它是否是同一個對象實例(引用比較)。

所以當我這樣做時:

var x = new pippo { abc = 1, fluido = 1};
var y = new pippo { abc = 1, fluido = 1};

我比較這兩個對象,它們不會相同,因為它們是兩個不同的實例(new 關鍵字可以創建一個新實例)。

深度對比

但是,當您對 String 類執行相同操作時:

var x = new String("hello world");
var y = new String("hello world");

而你比較這兩個 (x == y),那么結果是一樣的。 他們是怎么做到的?

他們通過覆蓋“對象”的默認行為並提供將這些對象與其他對象進行比較的新方法,重新定義了字符串比較自身的方式。

看看這里的一個很好的例子..

在您的情況下實現深度比較的正確方法是覆蓋“Equals”方法。 當你這樣做時,覆蓋“GetHashcode”方法也是一個好習慣。 他們實際上是一對。 事實上,如果您只是覆蓋這些方法之一而不是兩者,編譯器甚至會警告您。 為 pippo 執行此操作將如下所示:

public class pippo
{
  public int fluido;
  public int abc;

  public override bool Equals(object obj) 
  {
    // If this and obj do not refer to the same type, then they are not equal.
    if (obj.GetType() != this.GetType()) return false;

    // Return true if abc and fluido fields match.
    var other = (pippo) obj;
    return (this.abc == other.abc) && (this.fluido == other.fluido);
  }

  public override int GetHashCode() 
  {
    //something like this. 
    return ($"{this.abc}/{this.fluido}").GetHashCode();
  }
}

好的,現在 C# 知道如何檢查 pippos 是否“相等”。 現在,我們可以開始使用 C# / 或 LINQ 的內置列表操作來實現您想要的。

例如,要比較列表並插入和刪除元素,您可以這樣做

(這里可能有語法錯誤,但它應該顯示出竅門:

var newElements = lstact.Where(p=>!lstprec.Contains(p)).ToList();
var deletedElements = lstprec.Where(p=>!lstact.Contains(p)).ToList();

或者通過做這樣的事情:

 foreach(var p in lstprec)
 if(!lstact.Contains(p))
    ....

正如你所看到的,如果你在 pippo 類上投入一點,你可以做很多很酷的事情,而且你可以把它們做......

這是 linq 解決方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<pippo> lstact = new List<pippo>();
            List<pippo> lstprec = new List<pippo>();

            lstact.Add(new pippo { abc = 1, fluido = 1 });
            lstact.Add(new pippo { abc = 2, fluido = 1 });
            lstact.Add(new pippo { abc = 3, fluido = 1 });

            lstprec.Add(new pippo { abc = 1, fluido = 1 });
            lstprec.Add(new pippo { abc = 2, fluido = 1 });

            var matches = (from act in lstact
                           join prec in lstprec on act equals prec into pr
                           from prec in pr.DefaultIfEmpty()
                           select new { act = act, prec = prec }
                          ).ToList();

            foreach (var match in matches)
            {
                if(match.act == null)
                {
                    Console.WriteLine("B does not match A, abc = '{0}', prec = '{1}'", match.prec.abc, match.prec.fluido);
                }
                else
                {
                    if(match.prec == null)
                    {
                        Console.WriteLine("A does not match B, abc = '{0}', prec = '{1}'", match.act.abc, match.act.fluido);
                    }
                    else
                    {
                        Console.WriteLine("A matches B, abc = '{0}', prec = '{1}'", match.act.abc, match.act.fluido);
                    }
                }
            }
            Console.ReadLine();
        }
    }
    public class pippo : IEquatable<pippo>
    {
        public int abc { get;set;}
        public int fluido { get;set;}

        public Boolean Equals(pippo other)
        {
            return (this.abc == other.abc) && (this.fluido == other.fluido);
        }
        public override int  GetHashCode()
        {
            return (this.abc.ToString() + "^" + this.fluido.ToString()).GetHashCode();
        }

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM