2013-04-07 144 views
1

我描述的地址結構,它看起來像:如何爲地址結構生成唯一標識符?

class Address 
{ 
    public string AddressLine1 { get; set; } 
    public string AddressLine2 { get; set; } 
    public string City { get; set; } 
    public string Zip { get; set; } 
    public string Country { get; set; } 
} 

我正在尋找一種方法來創建這個結構的唯一標識符(我認爲它應該是一個類型的還string),這取決於所有的結構屬性(例如AddressLine1的改變也將導致結構標識符的改變)。

我知道,我可以將所有屬性連接在一起,但是這會給出太長的標識符。我正在尋找比這更短的東西。

我還假設不同地址的數量不應該超過100M。

有關如何生成此標識符的任何想法?

在此先感謝。

這方面的一個史前:

有在舉辦一些信息+地址數據的數據庫幾個不同的表。數據以與上述類似的格式存儲。

不幸的是,將地址數據移動到一個單獨的表中現在非常昂貴,但我希望它將在未來完成。

我需要將一些額外的屬性與地址數據關聯起來,併爲此創建一個單獨的表。這就是爲什麼我需要唯一標識地址數據。

+0

請給我們更多的上下文。幾乎可以肯定有更好的方法來解決這個問題。 – 2013-04-07 11:54:50

+1

在一般意義上,沒有辦法做出完美的散列函數。您需要首先擁有所有這些100M獨特地址,然後纔有可以創建您的函數的算法和軟件,這些函數可以將每個地址映射到唯一的數字,而不必將它們全部存儲起來。正如喬恩所說,與嘗試創建完美的哈希值相比,很可能有更好的方法來處理您的問題。 – 2013-04-07 11:57:19

回答

3

將所有字段序列化爲較大的二進制值。例如使用正確的域分離連接。

然後用足夠長度的密碼散列對該值進行散列。我更喜歡256位,但128可能很好。碰撞是非常罕見的,散列很好,像SHA-256這樣的256位散列實際上是不可能的。

+0

感謝您的回答。這似乎是最簡單的解決方案。在問這個問題之前,我已經有了類似的東西:)但是我想等待,也許有人會爲此提供另一種解決方案。 – Alex 2013-04-07 13:34:53

0

下面是使用序列,SHA256散列和base64編碼(基於CodesInChaos答案)一個完整的例子:

using System; 
using System.IO; 
using System.Security.Cryptography; 
using System.Runtime.Serialization.Formatters.Binary; 

namespace Uniq 
{ 
    [Serializable] 
    class Address 
    { 
     public string AddressLine1 { get; set; } 
     public string AddressLine2 { get; set; } 
     public string City { get; set; } 
     public string Zip { get; set; } 
     public string Country { get; set; } 
    } 
    class MainClass 
    { 
     public static void Main (string[] args) 
     { 
      Address address1 = new Address(){AddressLine1 = "a1"}; 
      Address address2 = new Address(){AddressLine1 = "a1"}; 
      Address address3 = new Address(){AddressLine1 = "a2"}; 
      string unique1 = GetUniqueIdentifier(address1); 
      string unique2 = GetUniqueIdentifier(address2); 
      string unique3 = GetUniqueIdentifier(address3); 
      Console.WriteLine(unique1); 
      Console.WriteLine(unique2); 
      Console.WriteLine(unique3); 
     } 
     public static string GetUniqueIdentifier(object obj){ 
      if (obj == null) return "0"; 
      SHA256 mySHA256 = SHA256Managed.Create(); 
      BinaryFormatter formatter = new BinaryFormatter(); 
      MemoryStream stream = new MemoryStream(); 
      formatter.Serialize(stream, obj); 
      byte[] hash = mySHA256.ComputeHash(stream.GetArray()); 
      string uniqId = Convert.ToBase64String(hash); 
      return uniqId; 
     } 
    } 
} 

編輯:這是不使用BinaryFormatter版本。您可以將空表示和字段分隔符替換爲適合您需要的任何內容。

public static string GetUniqueIdentifier(object obj){ 
    if (obj == null) return "0"; 
    SHA256 mySHA256 = SHA256Managed.Create(); 
    StringBuilder stringRep = new StringBuilder(); 
    obj.GetType().GetProperties() 
       .ToList().ForEach(p=>stringRep.Append(
      p.GetValue(obj, null) ?? '¨' 
      ).Append('^')); 
    Console.WriteLine(stringRep); 
    Console.WriteLine(stringRep.Length); 
    byte[] hash = mySHA256.ComputeHash(Encoding.Unicode.GetBytes(stringRep.ToString())); 
    string uniqId = Convert.ToBase64String(hash); 
    return uniqId; 
} 
+2

我不喜歡爲此使用'BinaryFormatter'。你需要某種函數*保證*每次你調用它時都會得到相同的結果,不管你使用哪種版本的.net或者mono。我不認爲'BinaryFormatter'確實能保證。我可能會使用[netstrings](http://en.wikipedia.org/wiki/Netstring)和各個值的連接。 – CodesInChaos 2013-04-07 13:15:20

+0

你也有一個bug:'stream.GetBuffer()'應該是'stream.ToArray()'。 – CodesInChaos 2013-04-07 13:15:55

+0

更正並編輯。 – 2013-04-07 13:44:58