Переопределение GetHashCode объекта, содержащего универсальный массив

[Сначала создайте новый столбец, чтобы объединить оба столбца.

df1["new_column"] = df1.bla2.fillna(df1.bla1);

Затем объедините оба кадра и удалите дополнительные созданные столбцы.

df3 = pd.merge(df1, df2, how="inner", left_on="new_column", right_on="bla").drop(["new_column", "bla"], axis=1)
54
задан AGB 12 April 2016 в 10:02
поделиться

7 ответов

Из-за проблем, повышенных в этом потоке, я отправляю другой ответ, показывающий, что происходит, если Вы понимаете его превратно... главным образом, что Вы не можете использовать массив GetHashCode(); корректное поведение состоит в том, что никакие предупреждения не печатаются при выполнении его... переключают комментарии для фиксации его:

using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
    static void Main()
    {
        // first and second are logically equivalent
        SimpleTableRow<int> first = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6),
            second = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6);

        if (first.Equals(second) && first.GetHashCode() != second.GetHashCode())
        { // proven Equals, but GetHashCode() disagrees
            Console.WriteLine("We have a problem");
        }
        HashSet<SimpleTableRow<int>> set = new HashSet<SimpleTableRow<int>>();
        set.Add(first);
        set.Add(second);
        // which confuses anything that uses hash algorithms
        if (set.Count != 1) Console.WriteLine("Yup, very bad indeed");
    }
}
class SimpleTableRow<T> : IEquatable<SimpleTableRow<T>>
{

    public SimpleTableRow(int id, params T[] values) {
        this.Id = id;
        this.Values = values;
    }
    public int Id { get; private set; }
    public T[] Values { get; private set; }

    public override int GetHashCode() // wrong
    {
        return Id.GetHashCode() ^ Values.GetHashCode();
    }
    /*
    public override int GetHashCode() // right
    {
        int hash = Id;
        if (Values != null)
        {
            hash = (hash * 17) + Values.Length;
            foreach (T t in Values)
            {
                hash *= 17;
                if (t != null) hash = hash + t.GetHashCode();
            }
        }
        return hash;
    }
    */
    public override bool Equals(object obj)
    {
        return Equals(obj as SimpleTableRow<T>);
    }
    public bool Equals(SimpleTableRow<T> other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Id == other.Id && Values.SequenceEqual(other.Values);
    }
}
83
ответ дан Marc Gravell 7 November 2019 в 07:51
поделиться

FWIW, очень опасно использовать содержание Значений в Вашем хэш-коде. Необходимо только сделать это, если можно гарантировать, что это никогда не будет изменяться. Однако, так как это представлено, я не думаю, гарантируя, что это возможно. Хэш-код объекта никогда не должен изменяться. Иначе это теряет свое значение как ключ в Хеш-таблице или Словаре. Рассмотрите дефицитную ошибку использования объекта как ключ в Хеш-таблице, ее изменениях хэш-кода из-за внешнего влияния, и Вы больше не можете находить его в Хеш-таблице!

31
ответ дан Chin 7 November 2019 в 07:51
поделиться

Так как хэш-код является своего рода ключевым для того, чтобы хранить объект (lllike в хеш-таблице), я использовал бы просто идентификатор. GetHashCode ()

4
ответ дан Jhonny D. Cano -Leftware- 7 November 2019 в 07:51
поделиться

Как насчет чего-то как:

    public override int GetHashCode()
    {
        int hash = Id;
        if (Values != null)
        {
            hash = (hash * 17) + Values.Length;
            foreach (T t in Values)
            {
                hash *= 17;
                if (t != null) hash = hash + t.GetHashCode();
            }
        }
        return hash;
    }

Это должно быть совместимо с SequenceEqual, вместо того, чтобы делать ссылочное сравнение на массиве.

2
ответ дан Marc Gravell 7 November 2019 в 07:51
поделиться
public override int GetHashCode() {
   return Id.GetHashCode() ^ Values.GetHashCode();  
}
<час>

существует несколько положительных сторон в комментариях и других ответах. OP должен рассмотреть, использовались ли Значения в качестве части "ключа", если объект использовался в качестве ключа в словаре. Если так, тогда они должны быть частью хэш-кода, иначе, нет.

, С другой стороны, я не уверен, почему метод GetHashCode должен зеркально отразить SequenceEqual. Это предназначено, чтобы вычислить индекс в хэш-таблицу, не быть полным детерминантом равенства. Если существует много коллизий хэш-таблицы с помощью алгоритма выше, и если они отличаются по последовательности Значений, то алгоритм должен быть выбран, который принимает последовательность во внимание. Если последовательность действительно не имеет значения, экономит время и не принимает его во внимание.

1
ответ дан Hakan Fıstık 7 November 2019 в 07:51
поделиться

Я сделал бы это этот путь:

long result = Id.GetHashCode();
foreach(T val in Values)
    result ^= val.GetHashCode();
return result;
0
ответ дан Grzenio 7 November 2019 в 07:51
поделиться

При условии, что идентификатор и Значения никогда не будут изменяться, и Значения не являются нулевыми...

public override int GetHashCode()
{
  return Id ^ Values.GetHashCode();
}

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

0
ответ дан Jason Plank 7 November 2019 в 07:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: