C # SetEquals на HashSetложь, когда ожидается истина - PullRequest
0 голосов
/ 01 июня 2018

Разработчик Python работает над C # (.NET 4.6, Visual Studio 2015 Professional).Я пытаюсь проверить, равны ли два HashSet с.

У меня есть два HashSet<List<float>>, которые я пытаюсь сравнить, используя

thisList.SetEquals(otherList);

Однако,это возвращает false на моих данных.Использование примера из примеров MSDN HashSet работает как положено.Однако в примерах они используют HashSet<int>, тогда как я использую HashSet<List<float>>.

Поскольку я не смог найти способ печати содержимого HashSet в Immediate Window в Visual Studio (ToString возвращает "System.Collections.Generic.HashSet1[System.Collections.Generic.List1[System.Single]]"), Я использую Json.NET JsonConvert.SerializeObject(thisList); для выгрузки данных в файл .json на диске.

Два файла (каждый для каждого HashSet содержимого: * 1028)*

[[10.0,15.0],[20.0,25.0]] и [[10.0,15.0],[20.0,25.0]]

Проверка HashSet s в Visual Studio при отладке выглядит следующим образом:

-       thisList    Count = 2   System.Collections.Generic.HashSet<System.Collections.Generic.List<float>>
-       [0] Count = 2   System.Collections.Generic.List<float>
        [0] 10  float
        [1] 15  float
+       Raw View        
-       [1] Count = 2   System.Collections.Generic.List<float>
        [0] 20  float
        [1] 25  float
+       Raw View        
+       Raw View        
-       otherList   Count = 2   System.Collections.Generic.HashSet<System.Collections.Generic.List<float>>
-       [0] Count = 2   System.Collections.Generic.List<float>
        [0] 20  float
        [1] 25  float
+       Raw View        
-       [1] Count = 2   System.Collections.Generic.List<float>
        [0] 10  float
        [1] 15  float
+       Raw View        
+       Raw View        

Каждый HashSet содержит два списка (порядокне имеет значения, так как это набор), и каждый список имеет одинаковые значения (с одинаковым порядком). Они должны считаться равными.

Что я должен сделать, чтобы эти HashSet считалисьравно thisList.SetEquals(otherList);?

РЕДАКТИРОВАТЬ:

Печать coord.ToString("G17") на каждом поплавке:

10
15
20
25
20
25
10
15

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Вы пытаетесь проверить равную операцию HashSet<List<float>> с другим объектом HashSet<List<float>>.Вопрос здесь в том, почему он возвращает false ?

Теперь, прежде чем говорить о HashSet<List<float>>, давайте поговорим о том, проверяю ли я равным (используя приведенный ниже код) для List<float> сдругой объект List<float>, тогда какой будет вывод?

    List<float> list = new List<float>() { 10.0f, 15.0f};
    List<float> anotherList = new List<float>() { 10.0f, 15.0f};

    Console.WriteLine(list.Equals(anotherList));

Вывод будет

false

Так как здесьEquals сравните ссылки объектов (которые не равны).

Теперь для решения вашей проблемы

При инициализации вы должны указать EqualityComparerHashSet, который должен проверять тип T при необходимости.

    HashSet<List<float>> HashSet1 = new HashSet<List<float>>(new FloatListComparer());
    anotherHashSet1.Add(list);

    HashSet<List<float>> anotherHashSet2 = new HashSet<List<float>>();
    anotherHashSet2.Add(anotherList);

    Console.WriteLine(anotherHashSet1.SetEquals(anotherHashSet2));

Вывод вышеприведенного кода:

true

Я написал здесь EqualityComparer выглядит следующим образом.

public class FloatListComparer : EqualityComparer<List<float>>
{
    public override bool Equals(List<float> list1, List<float> list2)
    {
        return list1.SequenceEqual(list2);
    }

    public override int GetHashCode(List<float> s)
    {
        return base.GetHashCode();
    }
}

Теперь возникает вопрос: почему SetEquals не работает

Если вы проверите реализацию SetEquals на здесь , то вы обнаружите, что этовызывает метод сравнения по умолчанию для T, который работает на основе проверки ссылки на объекты.Предоставляя Comparer, SetEquals использует указанный.

Проверьте актуальную фиддлер здесь .

0 голосов
/ 01 июня 2018

Поскольку вы используете List в своем HashSet, он сравнивает два списка как ссылки, а не рассматривает значения в списках.

Вместо использования List для представления X и Y, используйте класс Vector2 или Point.Примерно так должна выглядеть структура:

public struct Point
{
    public double X {get; }
    public double Y { get; }

    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }

    public bool Equals(Point other)
    {
        return X.Equals(other.X) && Y.Equals(other.Y);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is Point && Equals((Point) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (X.GetHashCode() * 397) ^ Y.GetHashCode();
        }
    }
}
...