C#比较两个相同对象类型的列表

6

我将尝试使用该类型的多个属性来比较两个相同类型的列表。

例如,

我有一个名为Details的类。

public class Details
{
    public   int id;
    public string symbol;
    public string code;
}

我有以下两个列表:

List<Details> list1 = new List<Details>();  
List<Details> list2 = new List<Details>();

list1.Add(new Details() { id=1,symbol="ANSI",code="NITE"});
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CANT" });
list1.Add(new Details() { id=2,symbol="ANSI",code="NITE"});
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CANT" });

list2.Add(new Details() { id = 1, symbol = "ANSI", code = "NITE" });
list2.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" });
list2.Add(new Details() { id = 2, symbol = "ANSI", code = "NITE" });

我希望从List1中仅获取具有相同id、symbol但不同code的数据。
因此,在上述情况下,结果将如下所示。
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CANT" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CANT" });

希望可以通过 Linq 实现,而不是使用 foreach。我尝试了以下方法,但不正确。
var temp =list1.Where(x=>list2.Any(z=>x.id==z.id && string.Equals(x.symbol,z.symbol) && !string.Equals(x.code,z.code)));

使用Join。请参阅msdn:https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b - jdweng
4个回答

7

看起来你需要满足两个条件才能生成输出结果:

  • idsymbol需要匹配,且
  • idsymbolcode不能都匹配。

以下是如何直接使用LINQ实现:

var tmp = list1.Where(x=>
    list2.Any(z=>x.id==z.id && x.symbol==z.symbol)
&& !list2.Any(z => x.id==z.id && x.symbol==z.symbol && x.code==z.code));

演示。

一种基于应用 德摩根定律 的替代方法:

var tmp = list1.Where(x=>
    list2.Any(z=>x.id==z.id && x.symbol==z.symbol)
 && list2.All(z => x.id!=z.id || x.symbol!=z.symbol || x.code!=z.code));

Demo.


6

1) 我会首先重写 Equals 方法(同时也需要重写 GetHashCode 方法)

public class Details
{
    public int id;
    public string symbol;
    public string code;

    public override int GetHashCode()
    {
        return (id + symbol + code).GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var other = obj as Details;
        if (other == null) return false;

        return id == other.id && symbol == other.symbol && code == other.code;
    }
}

那么你可以使用Linq,如下:

var result = list1.Except(list2).ToList();

它返回您期望的结果...


2) 通过实现自定义的IEqualityComparer,也可以在不更改Details对象的情况下获得相同的结果。

public class DetailsComparer : IEqualityComparer<Details>
{
    public bool Equals(Details x, Details y)
    {
        return x.id == y.id && x.symbol == y.symbol && x.code == y.code;
    }

    public int GetHashCode(Details obj)
    {
        return (obj.id + obj.symbol + obj.code).GetHashCode();
    }
}

然后你的linq将会是:
var result = list1.Except(list2, new DetailsComparer()).ToList();

这些方法比使用AnyAll的O(n*n)算法更好。


0

当然,你可以像你的代码一样进行比较,但如果你想让你的代码更有结构性,你可以重写方法Equals()和运算符==

public class Details
{
    public int id;
    public string symbol;
    public string code;

    public override bool Equals(System.Object obj)
    {
        if (obj == null) {
            return false;
        }

        Details detail = obj as Details;
        if ((System.Object) detail == null) {
          return false;
        }

        return (id == detail.id) && (symbol == detail.symbol);
    }

    public bool Equals(other) {
        return this.id == other.id && this.symbole == other.symbol;
    }

    public override int GetHashCode() {
        return id ^ symbol.GetHashCode();
    }
}

然后您可以直接比较两个详细对象。


-1
做这个:
public class DetailsComparer : IEqualityComparer<Details>
{

    public bool Equals(Details x, Details y)
        => x.id == y.id && x.symbol == y.symbol && x.code == y.code;

    public int GetHashCode(Details obj)
         => obj.code.GetHashCode();
}

并且非常简单的使用它

var x = list1.Except(list2, new DetailsComparer());

结果 x:

1、ANSI、CANT

2、ANSI、CALGO

3、ANSI、CANT


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接