Dictionary.ContainsKey для типа HashSet - Сравнить по элементам - PullRequest
0 голосов
/ 08 октября 2019

Я хочу добавить HashSet (который будет содержать 2 вектора) в словарь в качестве ключей. Позже я хочу (быстро) проверить, содержит ли словарь HashSet, который я создаю на лету из 2 векторов. Я хочу, чтобы проверка содержимого / равенства зависела от Векторов в наборе.

Fex. Если я добавлю HashSet [V000 V001] к Dict. Я хочу, чтобы Dict.ContainsKey (HashSet [V001 V000]) вернул true. (HashSet, поэтому порядок может отличаться, только одни и те же элементы)

Кажется, проблема в том, что Dict.ContainsKey видит отдельно созданные HashSets как разные объекты, даже если они содержат одинаковые элементы.

Dictionary<HashSet<Vector3>, Vector3> d = new Dictionary<HashSet<Vector3>, Vector3>();

HashSet<Vector3> s = new HashSet<Vector3>();
s.Add(Vector3.one);
s.Add(Vector3.zero);

d.Add(s);


HashSet<Vector3> s2 = new HashSet<Vector3>();
s2.Add(Vector3.zero);
s2.Add(Vector3.one);


bool doesContain = d.ContainsKey(s2);

Вы также можете рассмотреть лучший способ сделать эту проверку быстро. Я не совсем уверен, что это лучшее решение для того, что я делаю. Может быть, вы уже разобрались. Я проверяю, содержит ли общая группа ребер эту связь между двумя точками.

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Тип HashSet не выполняет сравнение равенства, которое вы хотите из коробки. Он имеет только ссылочное равенство.

Чтобы получить то, что вы хотите, вам потребуется новый тип для использования в качестве ключа словаря. Новый тип будет иметь свойство HashSet и перегрузку Equals() и GetHashCode(), а также может реализовывать IEquatable и на этом этапе.

Я начну с вас:

public class HashKey<T> : IEquatable<HashKey<T>>
{
    private HashSet<T> _items;
    public HashSet<T> Items
    {
        get {return _items;}
        private set {_items = value;}
    }

    public HashKey()
    {
        _items = new HashSet<T>();
    }
    public HashKey(HashSet<T> initialSet)
    {
        _items = initialSet ?? new HashSet();
    }

    public override int GetHashCode()
    {
        // I'm leaving this for you to do
    }

    public override bool Equals(Object obj)
    {
        if (! (obj is HashKey)) return false;
        return this.GetHashCode().Equals(obj.GetHashCode());
    }

    public bool Equals(HashSet<T> obj)
    {
        if (obj is null) return false;
        return this.GetHashCode().Equals(obj.GetHashCode());
    }
}      
0 голосов
/ 08 октября 2019

Вы хотите использовать хэш-набор в качестве ключа.

Таким образом, ключи являются ссылками, где один ключ является одной ссылкой на хэш-набор.

Сравнение ссылок ContainsKey.

Для того, что вы хотите сделать, вы можете создать класс, который реализует IEqualityComparer для передачи его в конструктор словаря.

https://docs.microsoft.com/dotnet/api/system.collections.generic.iequalitycomparer-1

Если вы хотите полное управление, вы должны создать новый класс, встраивающий словарь, и реализовать ваши собственные публичные операции, заключающие в себе словарь: ContainsKey и все другие необходимые вам методы.

public class MyDictionary : IEnumerable<>
{

  private Dictionary<HashSet<Vector3>, Vector3> d 
    = new Dictionary<HashSet<Vector3>, Vector3>();

  public int Count { get; }

  public this...

  public ContainsKey()
  {
    // implements your own comparison algorithm
  }

  public Add();

  public Remove();

  ...

}

Таким образом, у вас будет строго типизированный словарь для предполагаемого использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...