生成大小写字母加数字混合ID与自定义进制转换

介绍了一种利用自定义62进制数生成唯一ID的方法,并提供了具体的实现代码,该方法能够生成短小且按索引顺序排列的ID。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候可以在别的网站上看到类似于这样的ID : D6pPMSTjOFI, 关于数据库主键的选择园子里面也讨论过许多了,比如这篇 小议数据库主键选取策略(原创). 字符串作ID有时候还是有它的优点的,但是如何生成不重复且易于生成按索引顺序排列的ID呢.  原来我是用的 DateTime.Now.Ticks 可以产生一个long类型的时间刻度值,后来要用字符串的,就把这个转成16进制的, 当然也可以工作,但是似乎还是太长了一点,于是想到能不能创建自己的"进制数"呢,按unicode的编码, 从小到大应该是数字, 大写字符,小写字符,把它们放在一起可以形成一个62元素的数组,这就可以构成一个"62进制"的数了.

不过没有看.net框架里面的进制转换实现方案,本人不才自己写了一个来玩, 目前看来还可以工作, 有兴趣的高手看看可以怎么改进改进. 可以将int, uint, long, ulong(暂不支持负数转换)转换成字符型的值. 算法不是很难,因为ulong的最大值只需要11位的字符串就可以表示了因此结果采用一个11元素的字符串数组来装, 首先确定转换出来的数有几个位数,接着按从高到低的数位进行计算, 比如10进制里面的 520 = 5*10*10 + 2*10 + 0 , 因此计算过一位的值之后减去它再计算下一位的值,采用递归调用直到最低位.然后将字符串数组拼装成完整字符返回就完成了.

采用时间刻度生成的ID应该可以按索引顺序插入吧,会不会出现GUID那样数据越多,插入越慢的情况? 我觉得不会, 有待数据库专家论证.

要反向转换就比较容易了,代码就不再给出.

代码如下,

Code
using System;
using System.Collections.Generic;
using System.Text;

namespace MyTest.Core
{
    
public class MyIdentityConverter
    
{
        
/**//// <summary>
        
/// 用一个长度为11的数组用来存储最后的结果.
        
/// </summary>
        
/// <param name="sq">当前幂次方</param>
        
/// <param name="data"></param>
        
/// <returns></returns>

        public string[] ConvertTo62(ulong orgin)
        
{
            
return ConvertTo62(new string[11], -2, orgin);
        }


        
public string[] ConvertTo62(int orgin)
        
{
            
return ConvertTo62(new string[11], -2, (ulong)orgin);
        }


        
public string[] ConvertTo62(uint orgin)
        
{
            
return ConvertTo62(new string[11], -2, (ulong)orgin);
        }


        
public string[] ConvertTo62(long orgin)
        
{
            
return ConvertTo62(new string[11], -2, (ulong)orgin);
        }


        
private string[] ConvertTo62(string[] desCode, int sq, ulong orgin)
        
{
           
            
if (sq == -1)
                
return desCode;//递减时已经计算完低位.

            
if (desCode.Length != 11 || orgin < 0)
                
throw new Exception("参数无效!");

            
if (sq == -2)//使用-2作为初始值. 开始计算.
            {
                Console.WriteLine(
"初始值origin : " + orgin.ToString());
                
for (int i = 1; i < data.Length; i++)
                
{
                    
if (orgin < data[i])
                    
{
                        sq 
= i ;
                        
break;
                    }

                    
else if (i == data.Length - 1)
                    
{
                        sq 
= 11;
                        
break;
                    }

 
                }

                Console.WriteLine(
"目标位数 : " + sq.ToString());
            }


            
if (sq < 0)
                
throw new Exception("出错啦");

            
int currnetChar = -1;

            
for (int k = 0; k < 62; k++)
            
{
                
if (orgin < (ulong)k * data[sq -1])
                
{
                    currnetChar 
= k - 1;
                    orgin 
-= (ulong)(k-1* data[sq -1];
                    Console.WriteLine(
"当前计算值 : " + orgin);
                    
break;
                }

                
else if (k == 61)
                
{
                    currnetChar 
= 61;
                    orgin 
-= (ulong)61 * data[sq - 1];
                    Console.WriteLine(
"当前计算值 : " + orgin);
                    
break;
                }

            }

            Console.WriteLine(
"当前位字符索引 : " + currnetChar.ToString());

            desCode[
11- sq] = charactor[currnetChar].ToString();
            sq 
-= 1;
            
if (sq > 0)
                
return ConvertTo62(desCode, sq, orgin);
            
else
                
return desCode;
        }


        
static readonly ulong[] data = new ulong[] 16238442383281477633691613283256800235584352161460620821834010558489613537086546263552839299365868340224 };
        
static readonly char[] charactor = new char[] '0','1','2','3','4','5','6','7','8','9''A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R',
            
'S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' }
;
    }

}

再附上单元测试 :

Code
       [Test]
        
public void ConverterTest()
        
{
            MyIdentityConverter converter 
= new MyIdentityConverter();

            
string[] descode = converter.ConvertTo62(DateTime.Now.Ticks);
            Console.WriteLine(
"转换结果 : " + string.Join(string.Empty,descode));

            
string[] descode1 = converter.ConvertTo62(int.MaxValue);
            Console.WriteLine(
"转换结果 : " + string.Join(string.Empty, descode1));

            
string[] descode2 = converter.ConvertTo62(uint.MaxValue);
            Console.WriteLine(
"转换结果 : " + string.Join(string.Empty, descode2));

            
string[] descode3 = converter.ConvertTo62(ulong.MaxValue);
            Console.WriteLine(
"转换结果 : " + string.Join(string.Empty, descode3));

            DateTime dt 
= new DateTime(20051220);//这里使用时间刻度来创建一个唯一的ID.
            string[] descode4 = converter.ConvertTo62(DateTime.Now.Ticks - dt.Ticks);
            Console.WriteLine(
"转换结果 : " + string.Join(string.Empty, descode4));

            Assert.IsTrue(
true);
        }

在沙加的神舟本上完成的单元测试控制台输出:






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值