比较复杂对象的两个列表

问题描述 投票:0回答:2

我正在比较两个复杂对象列表,以查找插入的元素,修改的元素和删除的元素:

小例子

  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


    }
}
c# .net list object compare
2个回答
0
投票

这里是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();
        }

    }

}

0
投票

有很多快速的方法可以实现。这是一个非常正确的方法:

第一件事:对象比较基础

在C#中,每个类都源于“对象”类。 “对象”为每个类提供了一种基本的比较方式,方法是说:当我在同一实例中(在内存中相同的位置)时,我就等于。

所以:通常,当您比较两个对象时,没有定义其他任何内容,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),则结果相同。他们是如何做到的?

[它们通过重写“对象”的默认行为并提供了一种将这些对象与其他对象进行比较的新方式,重新定义了字符串比较自己的方式。

HERE为例,好..

您的情况进行深度比较的正确方法是覆盖“等于”方法。并且,当您这样做时,也最好重写“ GetHashcode”方法。

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() 
  {
    return (this.abc + this.fluido).GetHashCode();
  }
}

OK,现在编译器知道两个对象何时是“相同”的。很酷,因此我们现在可以使用C#的内置列表操作来实现您想要的功能,例如,在插入之前检查列表是否包含我的对象。]]]

例如,这样做(这里可能存在语法错误,但是应该显示出窍门:

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

或通过做类似的事情:

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

正如您所看到的,如果您对pippo类投入一些,就可以做很多很酷的事情,并且可以正确地做它们...

var removed = lstact.Where(p=>lstc
© www.soinside.com 2019 - 2024. All rights reserved.