0

我在寻找一种简单的方法来比较和证明两个列表的内容相等时遇到了一些令人沮丧的事情。我在 stackoverflow 上查看了许多解决方案,但都没有成功。一些解决方案看起来需要大量的工作来实现,并且做一些在我看来应该更简单的事情,但也许我太简单了,无法意识到这不能简单地完成:)

我创建了一些细节的小提琴,可以在这里查看:https ://dotnetfiddle.net/cvQr5d

finalResult或者,请在下面找到完整示例,我在返回对象比较方法(变量)时遇到问题,false如果正在比较内容,我希望该值为true

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

public class ResponseExample
{
    public Guid Id { get; set; } = Guid.Parse("00000000-0000-0000-0000-000000000000");
    public int Value { get; set; } = 0;
    public string Initials { get; set; } = "J";
    public string FirstName { get; set; } = "Joe";
    public string Surname { get; set; } = "Blogs";
    public string CellPhone { get; set; } = "0923232199";
    public bool EmailVerified { get; set; } = false;
    public bool CellPhoneVerified { get;  set; } = true;
}

public class Program
{
    public static void Main()
    {
        var responseOne = new ResponseExample();
        var responseTwo = new ResponseExample();
        var responseThree = new ResponseExample();
        var responseFour = new ResponseExample();
        
        List<ResponseExample> objectListOne = new List<ResponseExample>();
        objectListOne.Add(responseOne);
        objectListOne.Add(responseTwo);
        
        List<ResponseExample> objectListTwo = new List<ResponseExample>();
        objectListTwo.Add(responseThree);
        objectListTwo.Add(responseFour);

        bool result = objectListOne.Count == objectListTwo.Count();
        Console.WriteLine($"Count: {result}");
        bool finalResult = ScrambledEquals<ResponseExample>(objectListOne, objectListTwo);
        Console.WriteLine($"Object compare: {finalResult}");
    }
    
    //https://stackoverflow.com/a/3670089/3324415
    public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2)
    {
        var cnt = new Dictionary<T,
          int>();
        foreach (T s in list1)
        {
            if (cnt.ContainsKey(s))
            {
                cnt[s]++;
            }
            else
            {
                cnt.Add(s, 1);
            }
        }
        foreach (T s in list2)
        {
            if (cnt.ContainsKey(s))
            {
                cnt[s]--;
            }
            else
            {
                return false;
            }
        }
        return cnt.Values.All(c => c == 0);
    }
}
4

4 回答 4

1

正如评论中的人指出的那样,这将不起作用,因为默认情况下比较复杂类型会比较引用是否相同。如果不实现相等方法,逐字段比较将不起作用(然后您需要重载 GetHashCode 等)。请参阅https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?view=net-5.0

但是,如果您可以使用 c# 9,这就是您在小提琴中所拥有的,您可以将类型定义为 arecord而不是class. 记录已内置逐场比较。请参阅https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#characteristics-of-records

public class ResponseExample会变成这样public record ResponseExample,您的代码会按预期工作。

于 2021-08-11T17:22:33.637 回答
0

使用Enumerable.All<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) Methodwhich 确定序列的所有元素是否满足条件。

一旦你初始化了你的两个列表

list1.All(x=>list2.Contains(x))

这通过确保 list2 中的所有元素都包含在 list1 中来工作,否则返回 false

于 2021-08-11T17:16:39.500 回答
0

您的方法将比较这两个列表是否包含相同的对象。所以它返回 false 因为有 4 个不同的对象。如果您像这样使用相同的对象创建列表,它将返回 true:

        List<ResponseExample> objectListOne = new List<ResponseExample>();
        objectListOne.Add(responseOne);
        objectListOne.Add(responseTwo);

        List<ResponseExample> objectListTwo = new List<ResponseExample>();
        objectListTwo.Add(responseTwo);
        objectListTwo.Add(responseOne);

要在对象的内容相同时获得真实值,您可以将对象序列化为 json 字符串,如下所示:

    public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2)
    {
        JavaScriptSerializer json = new JavaScriptSerializer();

        var cnt = new Dictionary<string,
          int>();
        foreach (T _s in list1)
        {
            string s = json.Serialize(_s);
            if (cnt.ContainsKey(s))
            {
                cnt[s]++;
            }
            else
            {
                cnt.Add(s, 1);
            }
        }
        foreach (T _s in list2)
        {
            string s = json.Serialize(_s);
            if (cnt.ContainsKey(s))
            {
                cnt[s]--;
            }
            else
            {
                return false;
            }
        }
        return cnt.Values.All(c => c == 0);
    }
于 2021-08-11T17:20:52.807 回答
0

如果性能不是什么大问题,可以使用Newtonsoft.Json。我们将能够比较不同类型的对象并运行深度相等检查。

首先安装软件包:

Install-Package Newtonsoft.Json

这是代码片段:

public static bool DeepEqualsUsingJson<T>(IList<T> l1, IList<T> l2)
{
    if (ReferenceEquals(l1, l2))
        return true;

    if (ReferenceEquals(l2, null))
        return false;

    if (l1.Count != l2.Count)
        return false;

    var l1JObject = l1.Select(i => JObject.FromObject(i)).ToList();
    var l2JObject = l2.Select(i => JObject.FromObject(i)).ToList();

    foreach (var o1 in l1JObject)
    {
        var index = l2JObject.FindIndex(o2 => JToken.DeepEquals(o1, o2));
        if (index == -1)
            return false;
        l2JObject.RemoveAt(index);
    }

    return l2JObject.Count == 0;
}
于 2021-08-11T17:35:34.393 回答