Словарь. ContainsKey возвращают False, но хотение Верного

Я думаю, что вы пытаетесь выполнить одну из следующих операций (equlvalent):

x_does_work = x[row_indices,:][:,col_indices]
x_does_work = x[:,col_indices][row_indices,:]

Это фактически создаст подмножество из x только с выбранными строками, затем выберите столбцы из это, или наоборот во втором случае. Первый случай можно рассматривать как

x_does_work = (x[row_indices,:])[:,col_indices]
18
задан Giorgi 10 June 2010 в 13:52
поделиться

12 ответов

Вы хотите истину, но a и b - разные объекты.

Вам необходимо переопределить GetHashCode и Equals в классе Key

public class Key
{
    string name;
    public Key(string n) { name = n; }

    public override int GetHashCode()
    {
        if (name == null) return 0;
        return name.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        Key other = obj as key;
        return other != null && other.name == this.name;
    }
}
36
ответ дан 30 November 2019 в 06:07
поделиться

они имеют одни и те же значения внутри, но a! = B, поскольку они являются 2 разными переменными.

0
ответ дан 30 November 2019 в 06:07
поделиться

ContainsKey в этом случае сравнивает Key как объекты и проверяет, совпадают ли сами объекты - нет. Вам нужно реализовать IComparable или переопределить Key.Equals или что-то в этом роде, чтобы заставить его делать то, что вы хотите.

-1
ответ дан 30 November 2019 в 06:07
поделиться

Вероятно, поможет, если вы переопределите Key.GetHashCode и Key.Equals.

В Ключ :

public override bool Equals(object obj)
{
    var k = obj as Key;
    if (k != null)
    {
        return this.name == k.name;
    }
    return base.Equals(obj);
}

public override int GetHashCode()
{
    return this.name.GetHashCode();
}
8
ответ дан 30 November 2019 в 06:07
поделиться

ваша проблема в том, что

new Key("A").Equals(new Key("A"))==false.

и

new Key("A").GetHashCode()!=new Key("A").GetHashCode()

исправьте это, и все должно работать, я думаю. Чтобы исправить это, переопределите метод Equals и проверьте, одинаковы ли значения имен. Вы также должны переопределить GetHashCode, если вы переопределяете Equals.

1
ответ дан 30 November 2019 в 06:07
поделиться

Переопределение методов GetHashCode и Equals класса, чтобы они правильно работали в словаре, - не очень хороший подход. То, как ведет себя словарь, должно быть деталью реализации словаря, а не того класса, который используется в качестве ключа. У вас возникнут проблемы, если вы захотите использовать класс в разных словарях с разным поведением. Или если у вас нет доступа к исходному коду класса.

Лучшая ловушка для мыши - дать словарю собственный компаратор. Например:

using System;
using System.Collections.Generic;

class Program {
    static void Main(string[] args) {
        var d = new Dictionary<Key, int>(new MyComparer());
        d.Add(new Key("A"), 1);
        Console.WriteLine(d.ContainsKey(new Key("a")));
        Console.ReadLine();
    }
    private class MyComparer : IEqualityComparer<Key> {
        public bool Equals(Key x, Key y) {
            return string.Compare(x.Name, y.Name, true) == 0;
        }
        public int GetHashCode(Key obj) {
            return obj.Name.ToUpper().GetHashCode();
        }
    }
    public class Key {
        public string Name { get; set; }
        public Key(string name) { Name = name; }
    }
}
4
ответ дан 30 November 2019 в 06:07
поделиться

вам нужно переопределить методы Equals и GetHashCode вашего класса Key.

1
ответ дан 30 November 2019 в 06:07
поделиться

Вам необходимо переопределить методы Equals и GetHashCode вашего класса Key. В вашем случае вы могли бы сравнивать на основе имени ключа (или любого другого уникального свойства, если ваш класс более сложный).

public class Key {
    string name;
    public Key(string n) { name = n; }

    public override bool Equals(object obj) {
        Key k = obj as Key;
        if (k == null)
            return false;
        return name.Equals(k.name);
    }

    public override int GetHashCode() {
        return name.GetHashCode();
    }
}
0
ответ дан 30 November 2019 в 06:07
поделиться

Затем вам нужно будет переопределить GetHashCode и Equals в классе Key.

Без этого вы получите реализацию обоих по умолчанию. В результате хэш-код для a и b, скорее всего, не будет одинаковым (я не знаю, как выглядит реализация по умолчанию), а a будет определенно не равным b (реализация Equals () по умолчанию проверяет ссылочное равенство ).

В вашем случае, если предположить, что «name» не является нулем, это может быть реализовано как

   public class Key
   {
        string name;
        public override int GetHashCode()
        {
             return name.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
              return false;
            }

            Key objAsKey = obj as Key;
            if (objAsKey == null)
            {
              return false;
            }

            return this.name.Equals(objAsKey.Name);
        }
    }

Является ли это удовлетворительным хешем - это другая история, но, тем не менее, он показывает принцип.

0
ответ дан 30 November 2019 в 06:07
поделиться

1. Переопределение Equals, получение хэш-кода и оператора '=='.

Класс Key должен переопределить Equals, чтобы Словарь мог определить, являются ли они одинаковыми. Реализация по умолчанию будет проверять только ссылки.

Здесь:

        public bool Equals(Key other)
        {
            return this == other;
        }

        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Key))
            {
                return false;
            }

            return this.Equals((Key)obj);
        }

        public static bool operator ==(Key k1, Key k2)
        {
            if (object.ReferenceEquals(k1, k2))
            {
                return true;
            }

            if ((object)k1 == null || (object)k2 == null)
            {
                return false;
            }

            return k1.name == k2.name;
        }

        public static bool operator !=(Key k1, Key k2)
        {
            if (object.ReferenceEquals(k1, k2))
            {
                return false;
            }

            if ((object)k1 == null || (object)k2 == null)
            {
                return true;
            }

            return k1.name != k2.name;
        }

        public override int GetHashCode()
        {
            return this.name == null ? 0 : this.name.GetHashCode();
        }

2. Если возможно, используйте структуру.

Вы должны использовать struct для неизменяемых типов данных, таких как этот, поскольку они передаются по значению. Это означает, что вы не сможете случайно вписать два разных значения в один и тот же ключ.

0
ответ дан 30 November 2019 в 06:07
поделиться

Для использования ваших собственных классов в качестве ключей словаря следует переопределить GetHashCode и Equals. В противном случае он будет использовать адрес памяти для проверки равенства.

    public class Key
    {
        string name;
        public Key(string n) { name = n; }

        public override int GetHashCode()
        {
            return name.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            var other = obj as Key;
            if( other == null )
                return false;

            return name == other.name;
        }
    }

2
ответ дан 30 November 2019 в 06:07
поделиться

Если у вас нет возможности переопределить операторы равенства / Equals / GetHashCode, как упоминалось другими (например, вы не контролируете исходный код объекта), вы можете предоставьте реализацию IEqualityComparer в конструкторе словаря для выполнения ваших проверок равенства.

class KeyComparer : IEqualityComparer<Key>
{
    public bool Equals(Key x, Key y)
    {
        return x.Name == y.Name;
    }

    public int GetHashCode(Key obj)
    {
        return obj.Name.GetHashCode();
    }
}

В его нынешнем виде ваш Key является ссылочным объектом, поэтому равенство определяется только по ссылке, если вы не укажете миру (или словарю) иное.

6
ответ дан 30 November 2019 в 06:07
поделиться