C# 是否有内置方法来比较集合?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43500/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:53:39  来源:igfitidea点击:

Is there a built-in method to compare collections?

提问by TimK

I would like to compare the contents of a couple of collections in my Equals method. I have a Dictionary and an IList. Is there a built-in method to do this?

我想在我的 Equals 方法中比较几个集合的内容。我有一个字典和一个 IList。有没有内置的方法来做到这一点?

Edited: I want to compare two Dictionaries and two ILists, so I think what equality means is clear - if the two dictionaries contain the same keys mapped to the same values, then they're equal.

编辑:我想比较两个字典和两个 IList,所以我认为相等的含义很清楚 - 如果两个字典包含映射到相同值的相同键,那么它们是相等的。

采纳答案by Glenn Slaven

Enumerable.SequenceEqual

Enumerable.SequenceEqual

Determines whether two sequences are equal by comparing their elements by using a specified IEqualityComparer(T).

通过使用指定的 IEqualityComparer(T) 比较它们的元素来确定两个序列是否相等。

You can't directly compare the list & the dictionary, but you could compare the list of values from the Dictionary with the list

您不能直接比较列表和字典,但可以将字典中的值列表与列表进行比较

回答by Mark Ingram

No, because the framework doesn't know how to compare the contents of your lists.

不,因为框架不知道如何比较列表的内容。

Have a look at this:

看看这个:

http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx

http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx

回答by aku

Take a look at the Enumerable.SequenceEqualmethod

看看Enumerable.SequenceEqual方法

var dictionary = new Dictionary<int, string>() {{1, "a"}, {2, "b"}};
var intList = new List<int> {1, 2};
var stringList = new List<string> {"a", "b"};
var test1 = dictionary.Keys.SequenceEqual(intList);
var test2 = dictionary.Values.SequenceEqual(stringList);

回答by Giovanni Galbo

I didn't know about Enumerable.SequenceEqual method (you learn something every day....), but I was going to suggest using an extension method; something like this:

我不知道 Enumerable.SequenceEqual 方法(你每天都在学习一些东西......),但我建议使用扩展方法;像这样:

    public static bool IsEqual(this List<int> InternalList, List<int> ExternalList)
    {
        if (InternalList.Count != ExternalList.Count)
        {
            return false;
        }
        else
        {
            for (int i = 0; i < InternalList.Count; i++)
            {
                if (InternalList[i] != ExternalList[i])
                    return false;
            }
        }

        return true;

    }

Interestingly enough, after taking 2 seconds to read about SequenceEqual, it looks like Microsoft has built the function I described for you.

有趣的是,在花了 2 秒钟阅读 SequenceEqual 之后,看起来微软已经构建了我为您描述的功能。

回答by Evil Andy

No. The collection framework doesn't have any concept of equality. If you think about it there is no way of comparing collections which isn't subjective. For instance comparing your IList to your Dictionary, would they be equal if all the keys were in the IList, all the values were in the IList or if both were in the IList? There is no obvious way of comparing these two collections without knowledge of what they are to be used for so a general purpose equals method makes no sense.

不。集合框架没有任何平等的概念。如果您考虑一下,没有办法比较非主观的集合。例如,将您的 IList 与您的字典进行比较,如果所有键都在 IList 中,所有值都在 IList 中,或者如果两者都在 IList 中,它们是否相等?在不知道它们的用途的情况下,没有明显的方法来比较这两个集合,因此通用的 equals 方法没有意义。

回答by user329244

.NET Lacks any powerful tools for comparing collections. I've developed a simple solution you can find at the link below:

.NET 缺乏用于比较集合的任何强大工具。我开发了一个简单的解决方案,您可以在以下链接中找到:

http://robertbouillon.com/2010/04/29/comparing-collections-in-net/

http://robertbouillon.com/2010/04/29/comparing-collections-in-net/

This will perform an equality comparison regardless of order:

无论顺序如何,这都将执行相等比较:

var list1 = new[] { "Bill", "Bob", "Sally" };
var list2 = new[] { "Bob", "Bill", "Sally" };
bool isequal = list1.Compare(list2).IsSame;

This will check to see if items were added / removed:

这将检查是否添加/删除了项目:

var list1 = new[] { "Billy", "Bob" };
var list2 = new[] { "Bob", "Sally" };
var diff = list1.Compare(list2);
var onlyinlist1 = diff.Removed; //Billy
var onlyinlist2 = diff.Added;   //Sally
var inbothlists = diff.Equal;   //Bob

This will see what items in the dictionary changed:

这将看到字典中的哪些项目发生了变化:

var original = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" } };
var changed = new Dictionary<int, string>() { { 1, "aaa" }, { 2, "b" } };
var diff = original.Compare(changed, (x, y) => x.Value == y.Value, (x, y) => x.Value == y.Value);
foreach (var item in diff.Different)
  Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value);
//Will output: a changed to aaa

回答by Allon Guralnek

As others have suggested and have noted, SequenceEqualis order-sensitive. To solve that, you can sort the dictionary by key (which is unique, and thus the sort is always stable) and then use SequenceEqual. The following expression checks if two dictionaries are equal regardless of their internal order:

正如其他人所建议和指出的那样,SequenceEqual是顺序敏感的。要解决这个问题,您可以按键(这是唯一的,因此排序始终稳定)对字典进行排序,然后使用SequenceEqual. 以下表达式检查两个字典是否相等,而不管它们的内部顺序如何:

dictionary1.OrderBy(kvp => kvp.Key).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key))


EDIT:As pointed out by Jeppe Stig Nielsen, some object have an IComparer<T>that is incompatible with their IEqualityComparer<T>, yielding incorrect results. When using keys with such an object, you must specify a correct IComparer<T>for those keys. For example, with string keys (which exhibit this issue), you must do the following in order to get correct results:

编辑:正如 Jeppe Stig Nielsen 所指出的,某些对象的IComparer<T>与它们的 不兼容IEqualityComparer<T>,从而产生不正确的结果。将键用于此类对象时,您必须IComparer<T>为这些键指定正确的值。例如,对于字符串键(显示此问题),您必须执行以下操作才能获得正确的结果:

dictionary1.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key, StringComparer.Ordinal))

回答by Desty

In addition to the mentioned SequenceEqual, which

除了提到的SequenceEqual 之外

is true if two lists are of equal length and their corresponding elements compare equal according to a comparer

如果两个列表的长度相等并且它们对应的元素根据比较器比较相等,则为真

(which may be the default comparer, i.e. an overriden Equals())

(这可能是默认的比较器,即 overriden Equals()

it is worth mentioning that in .Net4 there is SetEqualson ISetobjects, which

值得一提的是,在.Net4 中ISet对象上有SetEquals

ignores the order of elements and any duplicate elements.

忽略元素的顺序和任何重复的元素。

So if you want to have a list of objects, but they don't need to be in a specific order, consider that an ISet(like a HashSet) may be the right choice.

因此,如果您想要一个对象列表,但它们不需要按特定顺序排列,请考虑使用 an ISet(如 a HashSet)可能是正确的选择。

回答by tymtam

This is not directly answering your questions, but both the MS' TestTools and NUnit provide

这不是直接回答您的问题,但是 MS 的 TestTools 和 NUnit 都提供

 CollectionAssert.AreEquivalent

which does pretty much what you want.

这几乎可以满足您的需求。

回答by mbadeveloper

public bool CompareStringLists(List<string> list1, List<string> list2)
{
    if (list1.Count != list2.Count) return false;

    foreach(string item in list1)
    {
        if (!list2.Contains(item)) return false;
    }

    return true;
}