简体   繁体   English

C#比较对象列表的两个列表

[英]C# Comparing two lists of lists of objects

I don't know where I make a mistake, but i cannot compare two lists of lists of (for example) integers. 我不知道我在哪里犯错,但是我无法比较(例如)整数列表的两个列表。

Simple example: 简单的例子:

List<List<int>> A = new List<List<int>>();
A.Add(new List<int>(new int[] { 1 }));
A.Add(new List<int>(new int[] { 2 }));

List<List<int>> B = new List<List<int>>();
B.Add(new List<int>(new int[] { 1 }));

if (A.Contains(B[0])){
    Console.WriteLine("TRUE");
else{
    Console.WriteLine("FALSE");
}

returns False. 返回False。 What is the correct way to compare in this kind of situation? 在这种情况下进行比较的正确方法是什么? I tried also Intersect and Except with same result. 我也尝试了IntersectExcept相同的结果。

you can iterate through each list in A and compare it to B[0] with SequenceEqual : 您可以遍历A中的每个列表,并使用SequenceEqual将其与B [0]进行比较:

if (A.Any(list => list.SequenceEqual(B[0])))
{
    Console.WriteLine("TRUE");
}
else
{
     Console.WriteLine("FALSE");
}

will return true 将返回true

bool contains = A.Any(a => B.Any(b => b.OrderBy(x => x)
                                       .SequenceEqual(a.OrderBy(x => x))));

 [[1],[2]]    and [[3]]       => false
 [[1],[2]]    and [[1]]       => true
 [[2],[1]]    and [[1],[2]]   => true
 [[3],[4]]    and [[1],[2]]   => false
 [[1,2],[3]]  and [[2,1],[4]] => true

It might help to visualize this: 这可能有助于形象化:

A:
   A[0]:
       A[0][0]: 1
   A[1]:
       A[1][0]: 2
B:
   B[0]:
       B[0][0]: 1

When you call A.Contains() , you're asking whether the thing you're testing is either A[0] or A[1] . 调用A.Contains() ,您正在询问要测试的对象是A[0]还是A[1] Since you're passing it B , and B is neither of those two, it returns false. 由于您要传递B ,并且B都不是这两个,因此它返回false。 Even if you were to pass it B[0] or B[0][0] , you'd still get false, because none of those are the same object as A[0] or A[1] . 即使您将其传递给B[0]B[0][0] ,您仍然会得到false,因为这些都不是与 A[0]A[1] 相同的对象

SequenceEqual() is the function which will test whether the contents of two List are the same. SequenceEqual()函数将测试两个List的内容是否相同。 So you want to test whether either A[0] or A[1] is SequenceEqual to B[0] (ie either A[0][0] == B[0][0] or A[1][0] == B[0][0] ). 所以要测试是否任一A[0]A[1]SequenceEqualB[0] (即,或者A[0][0] == B[0][0]A[1][0] == B[0][0] )。

The best way to do this is with the LINQ function .Any() . 最好的方法是使用LINQ函数.Any() A.Any(a => a.SequenceEqual(B[0])) will test B[0] against everything in A . A.Any(a => a.SequenceEqual(B[0]))将针对A中的所有内容测试B[0] If you want to compare all B elements to all A elements, you'd need something more like A.Any(a => B.Any(b => a.SequenceEqual(b)) . This can be translated as: 如果要比较所有 B元素和所有 A元素,则需要更多类似A.Any(a => B.Any(b => a.SequenceEqual(b))可以转换为:

foreach (var a in A) // A[0], A[1], etc.
{ 
    foreach (var b in B) // B[0], B[1], etc.
    {
       // is our current a value matching the current b value?
       // i.e. A[0] is exactly the same as B[0] on the first pass
       if (a.SequenceEqual(b)) return true; 
    }
}
return false;

For reference types other than string, operator == returns true if its two operands refer to the same object. 对于字符串以外的引用类型,如果operator ==的两个操作数引用同一对象,则其返回true。 That's clearly not the case here you are comparing one list reference to another list reference. 显然,这里要比较一个列表引用和另一个列表引用的情况并非如此。

You are comparing lists, which by default are compared for reference equality. 您正在比较列表,默认情况下会比较这些列表以确保引用相等。 For this particular case you can use SequenceEqual extension in the following way: 对于这种特殊情况,您可以通过以下方式使用SequenceEqual扩展:

bool contains = A.Any(a => a.SequenceEqual(B[0]));
Console.WriteLine(contains);  

This may or may not be efficient enough for your purposes :) 对于您的目的而言,这可能会或可能不够高效:)

Another way to approach this is to write your own IEqualityComparer wrapper around SequenceEqual as described here: IEqualityComparer for SequenceEqual and then use it as parameter in your .Contains call. 解决此问题的另一种方法是围绕SequenceEqual编写您自己的IEqualityComparer包装,如下所述: .Contains IEqualityComparer ,然后将其用作.Contains调用中的参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM