关于c#:检查两个列表是否相等

Check if two lists are equal

本问题已经有最佳答案,请猛点这里访问。

我的课程如下:

1
2
3
4
public class Tag {
    public Int32 Id { get; set; }
    public String Name { get; set; }
}

我有两个标签列表:

1
2
List<Tag> tags1;
List<Tag> tags2;

我使用Linq的Select获取每个标签列表的ID。然后:

1
2
3
4
5
List<Int32> ids1 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids2 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids3 = new List<Int32> { 2, 1, 3, 4 };
List<Int32> ids4 = new List<Int32> { 1, 2, 3, 5 };
List<Int32> ids5 = new List<Int32> { 1, 1, 3, 4 };

IDS1应等于IDS2和IDS3…两个都有相同的数字。

IDS1不应等于IDS4和IDS5…

我尝试了以下方法:

1
2
var a = ints1.Equals(ints2);
var b = ints1.Equals(ints3);

但两者都给了我虚假的。

检查标签列表是否相等的最快方法是什么?

更新

我在找标签和书上的标签完全一样的帖子。

1
2
3
4
5
6
7
8
9
10
IRepository repository = new Repository(new Context());

IList<Tags> tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } };

Book book = new Book { Tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } } };

var posts = repository
  .Include<Post>(x => x.Tags)
  .Where(x => new HashSet<Int32>(tags.Select(y => y.Id)).SetEquals(book.Tags.Select(y => y.Id)))
  .ToList();

我使用的是实体框架,我得到了错误:

An exception of type 'System.NotSupportedException' occurred in mscorlib.dll but was not handled in user code

Additional information: LINQ to Entities does not recognize the method 'Boolean SetEquals(System.Collections.Generic.IEnumerable`1[System.Int32])' method, and this method cannot be translated into a store expression.

我如何解决这个问题?


使用SequenceEqual检查序列是否相等,因为Equals方法检查引用是否相等。

1
var a = ints1.SequenceEqual(ints2);

或者,如果您不关心元素顺序,请使用Enumerable.All方法:

1
var a = ints1.All(ints2.Contains);

第二个版本还需要对Count进行另一个检查,因为即使ints2包含的元素多于ints1,它也会返回true。所以更正确的版本应该是这样的:

1
var a = ints1.All(ints2.Contains) && ints1.Count == ints2.Count;

为了检验不等式,只需颠倒All方法的结果:

1
var a = !ints1.All(ints2.Contains)


List相等不逐元素检查它们。您可以使用Linq的SequenceEqual方法:

1
var a = ints1.SequenceEqual(ints2);

若要忽略订单,请使用SetEquals

1
var a = new HashSet<int>(ints1).SetEquals(ints2);

这应该有效,因为您正在比较不包含重复项的ID序列。如果是这样,并且您需要考虑重复,那么在线性时间内这样做的方法是编写一个基于哈希的计数字典,为第一个序列的每个元素添加一个,为第二个序列的每个元素减去一个,并检查结果计数是否都为零:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var counts = ints1
    .GroupBy(v => v)
    .ToDictionary(g => g.Key, g => g.Count());
var ok = true;
foreach (var n in ints2) {
    int c;
    if (counts.TryGetValue(n, out c)) {
        counts[n] = c-1;
    } else {
        ok = false;
        break;
    }
}
var res = ok && counts.Values.All(c => c == 0);

最后,如果您对O(N*LogN)解决方案不满意,可以对这两个序列进行排序,并使用SequenceEqual比较它们是否相等。


1
2
Enumerable.SequenceEqual(FirstList.OrderBy(fElement => fElement),
                         SecondList.OrderBy(sElement => sElement))