2013-04-07 130 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

相关问题