【问题标题】:How do I create a unique identifier that does not contain numbers?如何创建不包含数字的唯一标识符?
【发布时间】:2013-09-09 20:08:55
【问题描述】:

我希望在 .resx 文件中使用某种唯一标识符,但它不允许密钥以数字开头。与其循环遍历 GUID,直到我得到一个以字母开头的 GUID,我想知道是否有另一种不包含数字或满足此要求的 UID 类型。

有什么想法吗?

【问题讨论】:

    标签: c# guid uniqueidentifier uid


    【解决方案1】:

    如果您只想创建一个以字母开始的 Guid,您可以执行以下操作:

    var b = Guid.NewGuid().ToByteArray();
    b[3] |= 0xF0;
    return new Guid(b);
    

    这将始终生成一个以十六进制数字 F 开头的 GUID。

    要创建一个不包含任何数字的 Guid,您可以使用如下内容:

    return new Guid(Guid.NewGuid().ToByteArray()
        .Select(b => (byte)(((b % 16) < 10 ? 0xA : b) | 
                            (((b >> 4) < 10 ? 0xA : (b >> 4)) << 4)))
        .ToArray());
    

    这将测试每个十六进制数字(每个字节两个),如果小于 A,则将其强制转换为 A


    上述两种解决方案都会生成真正的Guid 对象,尽管添加的限制确实在一定程度上降低了生成的 GUID 的唯一性(在第二个示例中更是如此)。如果您不关心输出是实际的 GUID,您可以简单地将十六进制数字重新映射到其他内容并将结果返回一个字符串,正如其他人所建议的那样。 FWIW,这是我能想到的最短解决方案:

    return String.Concat(Guid.NewGuid().ToString("N").Select(c => (char)(c + 17)));
    

    这会将十六进制数字 0 到 9 映射到字符 AJ,并将十六进制数字 A - F 映射到字符 rw。它还生成一个没有任何连字符的字符串。例如:

    Before: e58d0f329a2f4615b922ecf53dcd090a
    After:  vFIuAwDCJrCwEGBFsJCCvtwFDutuAJAr
    

    当然,如果您不喜欢这里的混合大小写,您可以将其全部转换为大写或小写。

    【讨论】:

    • @HamletHakobyan:即使是来自Guid.NewGuid 的新 GUID,完全没有修改,也不能保证是唯一的。这只是一个非常、非常、非常高的概率。
    • @HamletHakobyan 它肯定不像常规 Guid 那样独特,因为您将 GUID 限制为仅一小部分 Guid。甚至 GUID 也没有保证是唯一的,只有如此独特以至于您无法合理地期望在 Universe 的生命周期内找到重复项。您需要它们的独特程度取决于应用程序。
    • 我会说,不过,编辑(关于将所有数字强制转换为字母)确实将唯一性的可能性彻底摧毁了。它现在远低于 6^32 中的 1。
    • @HamletHakobyan How unique is UUID?
    • @Hamlet:除其他外,它的意思是“有限的数字”。事实是它们不能保证是唯一的。它们足够接近,您几乎可以在所有情况下都依靠唯一性……但是如果您需要绝对确定,则需要跟踪已经使用了哪些 GUID。因为如果重复是生死攸关的大事,1/2^122 远大于 0。
    【解决方案2】:

    如何生成一个唯一编号,然后在其前面加上一个字母?所以不是

    1234
    

    你会使用

    a1234
    

    只要您为标识符选择的算法保证一个唯一的数字,这应该可以正常工作。如果需要,它还可以让您去除前缀并再次将标识符用作数字。

    【讨论】:

      【解决方案3】:

      您可以编写和使用伪随机序列生成器。这是给出基本思想的一个:

      class RandomLetterSequence { 
          private static Random r; 
          private static char MinChar = (char) 0x0061; 
          private static char MaxChar = (char) 0x007A; 
      
          public static string RandomSequence() { 
              return RandomSequence(32);  
          }
      
          public static string RandomSequence(int length) { 
              if (r == null)
                  r = new Random(); 
              var sb = new StringBuilder(); 
              for (int i = length; i >= 0; i--) { 
                  sb.Append((char)(r.Next(MinChar, MaxChar))); 
              }
              return sb.ToString();
          }
      }
      

      使用此实现,可以生成 26^32 种符合您要求的不同序列:

      • 在碰撞率方面类似于 GUID(无限小)
      • 仅包含字母

      【讨论】:

        【解决方案4】:

        假设您不需要它成为有效的 Guid(您指的是“某种唯一标识符”),只需创建一个基于字符串的 guid(使用 Guid.NewGuid().ToString())然后将第一个数字映射到合适的字母,例如0=G、1=H、2=I 等

        【讨论】:

          【解决方案5】:

          只需编写您自己的类似 GUID 的生成器,有效的字符将是 a-z(您也可以使用 A-Z 来增加概率的数量)。

          【讨论】:

            【解决方案6】:

            生成新的 GUID 并将字符 0-9 替换为字符 g-p。

            【讨论】:

              【解决方案7】:

              @p.s.w.g 提供了很好的解决方案。

              您可以将他/她的建议写为扩展:

              using System;
              using System.Linq;
              
              namespace YourApp.Extensions.GuidExtensions
              {
                  public static class Extension
                  {
                      public static Guid FirstLetter(this Guid obj)
                      {
                          var b = obj.ToByteArray();
                          b[3] |= 0xF0;
                          return new Guid(b);
                      }
              
                      public static Guid OnlyLetters(this Guid obj)
                      {
                          var ba = obj.ToByteArray();
                          return new Guid(
                              ba.Select(b => (byte)(((b % 16) < 10 ? 0xA : b) |
                                                    (((b >> 4) < 10 ? 0xA : (b >> 4)) << 4)))
                                .ToArray()
                          );
                      }
                  }
              }
              

              然后在应用的某处使用它:

              // ...
              using YourApp.Extensions.GuidExtensions;
              // ...
              
              class SomeClass {
                  Guid SomeMethodWithFirstLetter() {
                      return Guid.NewGuid().FirstLetter();
                  }
              
              
                  Guid SomeMethodWithOnlyLetters() {
                      return Guid.NewGuid().OnlyLetters();
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2016-01-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-10-18
                • 1970-01-01
                • 1970-01-01
                • 2011-08-25
                相关资源
                最近更新 更多