2015-11-23 1 views
0

У меня есть коллекция, которая является перестановкой двух уникальных ордеров, где OrderId уникален. Таким образом, он содержит Order1 (Id = 1) и Order2 (Id = 2) как 12, так и 21. Теперь, обрабатывая алгоритм маршрутизации, проверяется несколько условий, и если комбинация включена в конечный результат, то ее обратное следует игнорировать и не нужно рассматривать для обработки. Теперь, так как Id является целым числом, я создал следующую логику:Создать уникальный Hashcode для перестановки двух идентификаторов заказа

private static int GetPairKey(int firstOrderId, int secondOrderId) 
     { 
      var orderCombinationType = (firstOrderId < secondOrderId) 
       ? new {max = secondOrderId, min = firstOrderId} 
       : new { max = firstOrderId, min = secondOrderId }; 

      return (orderCombinationType.min.GetHashCode()^orderCombinationType.max.GetHashCode()); 
     } 

В логике, я создаю Dictionary<int,int>, где ключ создается с помощью метода GetPairKey показано выше, где я убедиться, что из данной комбинации они упорядочены правильно, так что я получаю тот же Hashcode, который можно вставить и проверить для записи в словаре, в то время как его значение является фиктивным и его игнорируют.

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

Tuple.Create(minOrderId,maxOrderId).GetHashCode после уместно использование кода:

foreach (var pair in localSavingPairs) 
      { 
        var firstOrder = pair.FirstOrder; 
        var secondOrder = pair.SecondOrder; 

        if (processedOrderDictionary.ContainsKey(GetPairKey(firstOrder.Id, secondOrder.Id))) continue; 

Добавление в словарь, следующий код:

processedOrderDictionary.Add(GetPairKey(firstOrder.Id, secondOrder.Id), 0); здесь значение 0 манекен и не используется

+0

Если хеш-код является целым числом, а два идентификатора являются целыми числами, вы не можете создавать совершенно уникальные хэши из-за принципа [принципа голубей] (https://en.wikipedia.org/wiki/Pigeonhole_principle). У вас есть 2^32 возможных хэша и 2^63 кортежа, которым вы должны их назначить. – Kevin

+0

Можете ли вы показать код, который использует это со словарем? Из того, что вы описываете, это может быть далеко не оптимальным, но оно все равно должно работать. –

+0

Есть ли у меня возможность выполнить эту работу, чтобы получить уникальную комбинацию идентификаторов –

ответ

2

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

Это отличается от хэш-кода.

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

public class KeyPair : IEquatable<KeyPair> 
{ 
    public int Min { get; private set; } 
    public int Max { get; private set; } 

    public KeyPair(int first, int second) 
    { 
    if (first < second) 
    { 
     Min = first; 
     Max = second; 
    } 
    else 
    { 
     Min = second; 
     Max = first; 
    } 
    } 

    public bool Equals(KeyPair other) 
    { 
    return other != null && other.Min == Min && other.Max == Max; 
    } 

    public override bool Equals(object other) 
    { 
    return Equals(other as KeyPair); 
    } 

    public override int GetHashCode() 
    { 
    return unchecked(Max * 31 + Min); 
    } 
} 

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

Словарь будет использовать это, чтобы найти элемент, но он также будет использовать Equals, чтобы выбрать между теми, где хеш-код будет таким же.

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

+1

Возможно, вы захотите рассмотреть вопрос о включении вычисления хэш-кода с 'unchecked' – spender

+0

Это правильный ответ. Просто рассмотрение того, как вычислить хэш-код, не решит проблему OP. Ваш ответ можно улучшить, показав ему, что сам «KeyPair» используется как ключ словаря «Добавить». – ErikE

+0

@ErikE И, как ни странно, сам словарь будет внутренне вычислять хэш-код для пары таким образом, чтобы это было хорошим ответом для OP. – btilly

2

Во-первых, 42.GetHashCode() возвращает 42. Во-вторых, 1^2 идентичен 2^1, поэтому в сортировке nu нет смысла mbers. В-третьих, ваша «хеш-функция» очень слабая и вызывает много столкновений, поэтому вы наблюдаете недостатки.

Есть два варианта я могу думать прямо сейчас:

  • использовать немного «сильнее» hash function
  • Replace ваш Dictionary<int, int> ключ с Dictionary<string, int> с ключами быть ваши два отсортированных числа разделенных любого характера вы prever - например 56-6472
+0

Мое понимание остается Словарем, в котором я могу предоставить уникальную строку, как было предложено, с использованием любого приемлемого специального символа, такого как '-' или '%', всегда будет генерировать уникальный ключ для данной комбинации или у меня все еще есть область действия с ситуацией, где может быть столкновение –

2

Учитывая, что XOR коммутативности (так (a^b) всегда будет такой же, как (b^a)), мне кажется, что ваш заказ ошибочна ... Я просто

(new {firstOrderId, secondOrderId}).GetHashCode() 

.Net исправит вы используете хорошую хорошо распределенную реализацию хэширования для анонимных типов.

+0

Спасибо, позвольте мне попробовать, но все равно мне нужно будет правильно отсортировать идентификаторы, вот как бы я получил уникальный идентификатор для данной комбинации. –

+0

Что вы подразумеваете под «sort the ids»? Вы не гарантируете получение уникального хеш-кода, периода. –

+0

@MrinalKamboj Ah ... теперь мы переходим к другой проблеме вообще. Использование хэш-кода в качестве меры уникальности - ужасная идея. Нет никакой гарантии, что он создаст уникальный идентификатор. Это не то, для чего нужны хэш-коды.Если вы хотите получить гарантированное уникальное значение, тогда я бы подумал о 'long' с' (value1 << 32) + value2' – spender

 Смежные вопросы

  • Нет связанных вопросов^_^