5

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

有什么想法吗?

4

7 回答 7

12

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

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

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

要创建不包含任何数字的 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 映射到字符Athrough J,并将十六进制数字A-映射F到字符rthrough w。它还生成一个没有任何连字符的字符串。例如:

Before: e58d0f329a2f4615b922ecf53dcd090a
After:  vFIuAwDCJrCwEGBFsJCCvtwFDutuAJAr

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

于 2013-09-05T20:53:12.480 回答
3

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

1234

你会用

a1234

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

于 2013-09-05T20:58:14.347 回答
2

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

于 2013-09-05T20:59:36.107 回答
2

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

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(无限小)
  • 仅包含字母
于 2013-09-05T21:03:39.390 回答
1

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

于 2013-09-05T20:53:13.730 回答
1

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

于 2013-09-05T20:58:25.740 回答
0

@pswg 提供了很好的解决方案。

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

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();
    }
}
于 2019-10-30T10:00:25.403 回答