尽可能短的生成的唯一 ID
Shortest possible generated unique ID
所以我们可以generate a unique id with str(uuid.uuid4())
,也就是36个字符长。
是否有另一种方法可以生成字符数更短的唯一 ID?
编辑:
- 如果 ID 可以用作主键,那就更好了
- 粒度应优于 1ms
- 此代码可以分发,因此我们不能假设时间独立。
是的。只需使用当前的 UTC 毫秒。此号码永不重复。
const uniqueID = new Date().getTime();
EDIT
如果你很少需要在同一毫秒内产生多个ID,这种方法是没有用的,因为这个数字的粒度是1ms。
如果这是用作数据库中的主键字段,请考虑仅使用自动递增整数。
str(uuid.uuid4())
是 36 个字符,但其中有四个无用的破折号 (-
),并且限制为 0-9 a-f。
更好的 uuid4 32 个字符:
>>> uuid.uuid4().hex
'b327fc1b6a2343e48af311343fc3f5a8'
或者只是 b64 编码和切片一些 urandom 字节(由你来保证唯一性):
>>> base64.b64encode(os.urandom(32))[:8]
b'iR4hZqs9'
TLDR
大多数情况下,最好在内部处理数字并在外部将它们编码为短 ID。所以这是 Python3、PowerShell 和 VBA 的函数,它将 int32 转换为字母数字 ID。像这样使用它:
int32_to_id(225204568)
'F2AXP8'
对于分布式代码使用 ULID:https://github.com/mdipierro/ulid
它们更长,但在不同的机器上是独一无二的。
ID有多短?
它将在 6 个字符中编码大约 50 亿个 ID,因此它尽可能紧凑,同时仍然仅使用 non-ambiguous digits and letters。
如何获得更短的 ID?
如果您想要更紧凑的 IDs/codes/Serial 数字,只需更改 chars="..."
定义即可轻松扩展字符集。例如,如果您允许所有大小写字母,您可以在相同的 6 个字符中拥有 560 亿个 ID。添加几个符号(如 ~!@#$%^&*()_+-=
)即可得到 2080 亿个 ID。
那你为什么不选择尽可能短的 ID?
我在我的代码中使用的字符集有一个优势:它生成的 ID 易于复制粘贴(没有符号,因此双击选择整个 ID),易于阅读而不会出错(看不出来- 2
和 Z
之类的相似字符)并且很容易口头交流(只有大写字母)。只使用数字是口头交流的最佳选择,但它们并不紧凑。
我深信:给我看代码
Python 3
def int32_to_id(n):
if n==0: return "0"
chars="0123456789ACEFHJKLMNPRTUVWXY"
length=len(chars)
result=""
remain=n
while remain>0:
pos = remain % length
remain = remain // length
result = chars[pos] + result
return result
PowerShell
function int32_to_id($n){
$chars="0123456789ACEFHJKLMNPRTUVWXY"
$length=$chars.length
$result=""; $remain=[int]$n
do {
$pos = $remain % $length
$remain = [int][Math]::Floor($remain / $length)
$result = $chars[$pos] + $result
} while ($remain -gt 0)
$result
}
VBA
Function int32_to_id(n)
Dim chars$, length, result$, remain, pos
If n = 0 Then int32_to_id = "0": Exit Function
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result$ = ""
remain = n
Do While (remain > 0)
pos = remain Mod length
remain = Int(remain / length)
result$ = Mid(chars$, pos + 1, 1) + result$
Loop
int32_to_id = result
End Function
Function id_to_int32(id$)
Dim chars$, length, result, remain, pos, value, power
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result = 0
power = 1
For pos = Len(id$) To 1 Step -1
result = result + (InStr(chars$, Mid(id$, pos, 1)) - 1) * power
power = power * length
Next
id_to_int32 = result
End Function
Public Sub test_id_to_int32()
Dim i
For i = 0 To 28 ^ 3
If id_to_int32(int32_to_id(i)) <> i Then Debug.Print "Error, i=", i, "int32_to_id(i)", int32_to_id(i), "id_to_int32('" & int32_to_id(i) & "')", id_to_int32(int32_to_id(i))
Next
Debug.Print "Done testing"
End Sub
所以我们可以generate a unique id with str(uuid.uuid4())
,也就是36个字符长。
是否有另一种方法可以生成字符数更短的唯一 ID?
编辑:
- 如果 ID 可以用作主键,那就更好了
- 粒度应优于 1ms
- 此代码可以分发,因此我们不能假设时间独立。
是的。只需使用当前的 UTC 毫秒。此号码永不重复。
const uniqueID = new Date().getTime();
EDIT
如果你很少需要在同一毫秒内产生多个ID,这种方法是没有用的,因为这个数字的粒度是1ms。
如果这是用作数据库中的主键字段,请考虑仅使用自动递增整数。
str(uuid.uuid4())
是 36 个字符,但其中有四个无用的破折号 (-
),并且限制为 0-9 a-f。
更好的 uuid4 32 个字符:
>>> uuid.uuid4().hex
'b327fc1b6a2343e48af311343fc3f5a8'
或者只是 b64 编码和切片一些 urandom 字节(由你来保证唯一性):
>>> base64.b64encode(os.urandom(32))[:8]
b'iR4hZqs9'
TLDR
大多数情况下,最好在内部处理数字并在外部将它们编码为短 ID。所以这是 Python3、PowerShell 和 VBA 的函数,它将 int32 转换为字母数字 ID。像这样使用它:
int32_to_id(225204568)
'F2AXP8'
对于分布式代码使用 ULID:https://github.com/mdipierro/ulid
它们更长,但在不同的机器上是独一无二的。
ID有多短?
它将在 6 个字符中编码大约 50 亿个 ID,因此它尽可能紧凑,同时仍然仅使用 non-ambiguous digits and letters。
如何获得更短的 ID?
如果您想要更紧凑的 IDs/codes/Serial 数字,只需更改 chars="..."
定义即可轻松扩展字符集。例如,如果您允许所有大小写字母,您可以在相同的 6 个字符中拥有 560 亿个 ID。添加几个符号(如 ~!@#$%^&*()_+-=
)即可得到 2080 亿个 ID。
那你为什么不选择尽可能短的 ID?
我在我的代码中使用的字符集有一个优势:它生成的 ID 易于复制粘贴(没有符号,因此双击选择整个 ID),易于阅读而不会出错(看不出来- 2
和 Z
之类的相似字符)并且很容易口头交流(只有大写字母)。只使用数字是口头交流的最佳选择,但它们并不紧凑。
我深信:给我看代码
Python 3
def int32_to_id(n):
if n==0: return "0"
chars="0123456789ACEFHJKLMNPRTUVWXY"
length=len(chars)
result=""
remain=n
while remain>0:
pos = remain % length
remain = remain // length
result = chars[pos] + result
return result
PowerShell
function int32_to_id($n){
$chars="0123456789ACEFHJKLMNPRTUVWXY"
$length=$chars.length
$result=""; $remain=[int]$n
do {
$pos = $remain % $length
$remain = [int][Math]::Floor($remain / $length)
$result = $chars[$pos] + $result
} while ($remain -gt 0)
$result
}
VBA
Function int32_to_id(n)
Dim chars$, length, result$, remain, pos
If n = 0 Then int32_to_id = "0": Exit Function
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result$ = ""
remain = n
Do While (remain > 0)
pos = remain Mod length
remain = Int(remain / length)
result$ = Mid(chars$, pos + 1, 1) + result$
Loop
int32_to_id = result
End Function
Function id_to_int32(id$)
Dim chars$, length, result, remain, pos, value, power
chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
length = Len(chars$)
result = 0
power = 1
For pos = Len(id$) To 1 Step -1
result = result + (InStr(chars$, Mid(id$, pos, 1)) - 1) * power
power = power * length
Next
id_to_int32 = result
End Function
Public Sub test_id_to_int32()
Dim i
For i = 0 To 28 ^ 3
If id_to_int32(int32_to_id(i)) <> i Then Debug.Print "Error, i=", i, "int32_to_id(i)", int32_to_id(i), "id_to_int32('" & int32_to_id(i) & "')", id_to_int32(int32_to_id(i))
Next
Debug.Print "Done testing"
End Sub