通用列表比较/重复删除 [英] Generic list comparison / duplicate removal

查看:77
本文介绍了通用列表比较/重复删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 

大家好,

我想比较2个自定义对象列表。

这是我的设置:



 Class< Entity> 
{
string ID;
int 金额;

public 实体(字符串 _ID, int _Amount)
{
ID = _ID;金额= _Amount;
}
}

在下面的代码中我有这个:



 List< ;实体> E1 = mew List< Entity>(); 
列表<实体> E2 = mew List< Entity>();



 E1.Add( new 实体(  A1 1 )); 
E1.Add( new 实体( A1 1 ));
E1.Add( new 实体( B1 3 ));
E1.Add( new 实体( C1 5 ));

E2.Add( new 实体( A1 1 ));
E2.Add( new 实体( D1 7 ));
E2.Add( new 实体( F1 8 ));
E2.Add( new 实体( F1 8 ));





所以 - 第一个问题 - 如何从这两个列表中删除重复项? E1加倍[A1,1]组合,E2有[F1,8]组合。



我试过用过这个:

 E1 = E1.distinct()。ToList()
E2 = E2.distinct()。ToList()

但这没有帮助。 ..任何帮助将不胜感激。



问题#2。

我想要返回第3个列表,其中包含所有项目列表E1,但不在列表#2中。

我尝试过这个LINQ查询:

  var 区别=(来自项目  E2 
where !E1.Contains(item)
select item)。ToList();

虽然这不是安静的工作 - 它返回两个都存在的项目......所以我在这里安静迷失....我正在考虑在Entity类上实现IComparable接口,但不是很确定......如果你能至少向我展示正确的道路,或者举一些例子让我的大脑开启,我将不胜感激。



提前致谢!

解决方案

试试这个..







 使用 System.Collections.Generic; 
使用系统;
使用 System.Linq;


class 计划
{

static void Main( string [] args)
{
列表< entity> E1 = new 列表< entity>();
列表< entity> E2 = new 列表< entity>();
E1.Add( new 实体( A1 1 ));
E1.Add( new 实体( A1 1 ));
E1.Add( new 实体( B1 3 ));
E1.Add( new 实体( C1 5 ));

E2.Add( new 实体( A1 1 ));
E2.Add( new 实体( D1 7 ));
E2.Add( new 实体( F1 8 ));
E2.Add( new 实体( F1 8 ));
// 删除重复项

E1 = E1.Distinct( new EntityComparer())。ToList();
E2 = E2.Distinct( new EntityComparer())。ToList();

// 问题2

var newresult = E1.Where(k = > !E2.Contains(k, new EntityComparer()))。ToList();


Console.ReadLine();
}
}

class EntityComparer:IEqualityComparer< entity>
{
public bool 等于(实体x,实体y)
{
return x.ID == y.ID;
}


public int GetHashCode(实体) obj)
{
return 0 ;
}
}

class 实体
{
public string ID { get ; set ; }
public int 金额{ get ; set ; }

public 实体( string _ID, int _Amount)
{
ID = _ID;金额= _Amount;
}
}


如果你不想实现IEqualityComparer,就像Karthik整齐地告诉你该怎么做,那里是另一种选择:您需要在实体类中重写等于:

  public   class 实体
{
public string ID;
public int 金额;

public 实体(字符串 _ID, int _Amount)
{
ID = _ID;金额= _Amount;
}

public 覆盖 bool 等于(对象 obj)
{
实体e2 = obj as 实体;

// 边缘情况?是不是真的有必要?
// if(ReferenceEquals(this,e2))return true;

// if(e2 == null&& this! = null)返回false;

// if(this == null && e2!= null)返回false;

return this .ID == e2.ID&& this .Amount == e2.Amount;
}
}

然后你可以这样做:

 List< Entity> E1 =  new 列表< Entity>(); 
列表<实体> E2 = new 列表< Entity>();

private void TestListFilteringAndMerging(对象发​​件人,EventArgs e)
{
E1.Add( new 实体( A1 1 ));
E1.Add( new 实体( A1 1 ));
E1.Add( new 实体( B1 3 ));
E1.Add( new 实体( C1 5 ));

E2.Add( new 实体( A1 1 ));
E2.Add( new 实体( D1 7 ));
E2.Add( new 实体( F1 8 ));
E2.Add( new 实体( F1 8 ));

// test Equals override
// Console.WriteLine(E1 [0] .Equals(E2 [0]))。ToString());

// 消除每个列表中的重复项
E1 = E1.GroupBy (e1 = > e1.ID)。选择(e2 = > e2.First()) .ToList();
E2 = E2.GroupBy(e1 = > e1.ID)。选择(e2 = > e2.First())。ToList();

// 合并两个列表并消除合并列表中的重复项
列表<实体> JoinE1E2 = E1.Concat(E2).GroupBy(e1 = > e1.ID)。选择(e2 = > e2.First())。ToList();

// 检查合并列表
foreach (实体theEntity JoinE1E2中)
{
Console.WriteLine(theEntity.ID + + theEntity.Amount.ToString());
}
}

但是,我建议您继续使用Karthik向您展示的解决方案,因为:我认为它更具可读性,可能随着时间的推移更具可维护性。只是全能的标准。



我想在这里试图解释Linq的巧妙使用......甚至对自己来说,我感到不寒而栗:) />


并且,请注意VS 2013会给你一个警告(但不是停止编译),你没有覆盖'GetHashCode。


< blockquote>查看我过去的回答:如何比较一个数组中的日期 [ ^ ]。

Hello guys,
I am trying to compare 2 list of custom objects.
Here is my setup:

Class <Entity>
{
     string ID;
     int Amount;

     public Entity(string _ID, int _Amount)
     {
        ID = _ID; Amount = _Amount;
     }
}

In the further code I have this:

List<Entity> E1 = mew List<Entity>();
List<Entity> E2 = mew List<Entity>();


E1.Add(new Entity("A1", 1));
E1.Add(new Entity("A1", 1));
E1.Add(new Entity("B1", 3));
E1.Add(new Entity("C1", 5));

E2.Add(new Entity("A1", 1));
E2.Add(new Entity("D1", 7));
E2.Add(new Entity("F1", 8));
E2.Add(new Entity("F1", 8));



So - 1st question - how to remove duplicates from these 2 lists? E1 has doubled ["A1", 1] combination and E2 has ["F1", 8] combination.

I have tried using this:

E1 = E1.distinct().ToList()
E2 = E2.distinct().ToList()

But that did not help... any help would be appreciated.

Question #2.
I want to return 3rd list which would contain the items that are in list E1, but not in list #2.
I have tried this LINQ query:

var distinction = (from item in E2
                  where !E1.Contains(item)
                  select item).ToList();

Though that does not quiet work - it returns items that are present in both... so I'm quiet lost in here.... I was thinking about implementing IComparable interface on Entity class, but not really sure... would appreciate if you could at least show me the right path or give some example to turn my brains on :)

Thanks in advance!

解决方案

Try this..



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


class Program
{

    static void Main(string[] args)
    {
        List<entity> E1 = new List<entity>();
        List<entity> E2 = new List<entity>();
        E1.Add(new Entity("A1", 1));
        E1.Add(new Entity("A1", 1));
        E1.Add(new Entity("B1", 3));
        E1.Add(new Entity("C1", 5));

        E2.Add(new Entity("A1", 1));
        E2.Add(new Entity("D1", 7));
        E2.Add(new Entity("F1", 8));
        E2.Add(new Entity("F1", 8));
        // remove duplicates

        E1 = E1.Distinct(new EntityComparer()).ToList();
        E2 = E2.Distinct(new EntityComparer()).ToList();

        // question 2 

      var newresult = E1.Where(k => !E2.Contains(k, new EntityComparer())).ToList();   


        Console.ReadLine();
    }
}

class EntityComparer : IEqualityComparer<entity>
{ 
    public bool Equals(Entity x, Entity y)
    {
        return x.ID == y.ID; 
    }


    public int GetHashCode(Entity obj)
    {
        return 0;
    }
}

class Entity
{
    public string ID { get; set; }
    public int Amount { get; set; }

    public Entity(string _ID, int _Amount)
    {
        ID = _ID; Amount = _Amount;
    }
}


If you just don't feel like implementing an IEqualityComparer, as Karthik neatly shows you how to do, there is an alternative: you do need to override Equals in your Entity Class:

public class Entity
{
     public string ID;
     public int Amount;

     public Entity(string _ID, int _Amount)
     {
        ID = _ID; Amount = _Amount;
     }

     public override bool Equals(object obj)
     {
         Entity e2 = obj as Entity;

         // edge cases ? not really necessary ?
         //if (ReferenceEquals(this, e2)) return true;

         //if (e2 == null && this != null) return false;

         //if (this == null && e2 != null) return false;

         return this.ID == e2.ID && this.Amount == e2.Amount;
     }
}

Then you can do this:

List<Entity> E1 = new List<Entity>();
List<Entity> E2 = new List<Entity>();

private void TestListFilteringAndMerging(object sender, EventArgs e)
{
    E1.Add(new Entity("A1", 1));
    E1.Add(new Entity("A1", 1));
    E1.Add(new Entity("B1", 3));
    E1.Add(new Entity("C1", 5));

    E2.Add(new Entity("A1", 1));
    E2.Add(new Entity("D1", 7));
    E2.Add(new Entity("F1", 8));
    E2.Add(new Entity("F1", 8));

    // test Equals override
    // Console.WriteLine(E1[0].Equals(E2[0])).ToString());

    // eliminate duplicates in each List
    E1 = E1.GroupBy(e1 => e1.ID).Select(e2 => e2.First()).ToList();
    E2 = E2.GroupBy(e1 => e1.ID).Select(e2 => e2.First()).ToList();

    // merge two Lists and eliminate duplicates in merged List
    List<Entity> JoinE1E2 = E1.Concat(E2).GroupBy(e1 => e1.ID).Select(e2 => e2.First()).ToList();

    // examine merged List
    foreach(Entity theEntity in JoinE1E2)
    {
        Console.WriteLine(theEntity.ID + " : " + theEntity.Amount.ToString());
    }
}

However, I'd recommend you go ahead and use the solution Karthik showed you, because: I think it is more readable, probably more maintainable over time ... just all-around more "standard."

I shudder to think of trying to explain the clever use of Linq here ... even to myself :)

And, note that VS 2013 will give you a warning (but not stop compilation) that you have not over-ridden 'GetHashCode.


See my past answer: how to compare dates in one array[^].


这篇关于通用列表比较/重复删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆