怎么把 0~999999 的数字 映射成唯一的 长度固定为 8 的 0-9A-Z 组成的字符串?

2022-05-24 16:14:22 +08:00
 caqiko
# 对于任意一个 0~999999 之间的数字 num ,通过 func 转换得到一个 result
result = func(num)
# result 是由大写字母和数字 0-9 组成的字符串,长度固定为 8
# 如:func(1) = "A6FU1Y5F", func(2) = "YFS98TT2"
# 需要
# 1. 确保不同的输入 num 对应不同的输出 result ,
# 2. 要不容易通过已知的几个(num, result)映射找出规律,
# 3. 要能通过 result 逆向找回 num ,
# 4. 不能用写死的 dict 去做映射

我开始想的是,把数字前面补 0 ,补成 8 位 00000000~00999999
再做一个两位数字 00~99 对应两位字符串的一一映射{"00": "0A", "01": "0B", …}
然后每两位去拼出 result ,但是这样就很容易被找到规律,而且要写死一个很长的 dict ,很不优雅
不知道大佬们有没有什么好的思路?

1787 次点击
所在节点    Python
10 条回复
ChoateYao
2022-05-24 16:16:51 +08:00
这不就是 36 进制嘛
sujin190
2022-05-24 16:24:07 +08:00
字母数字转化为 charCode 之后就是连续的数字了,查一下 base64 的编码算法照着写一个 base36 就是了呗
liuidetmks
2022-05-24 16:27:35 +08:00
@sujin190 base36 可麻烦多了,做 base32 会简单很多,正好去掉一些容易混淆的. l1 0O
xaplux
2022-05-24 16:28:07 +08:00
找一个基准时间戳,36 进制(基准时间戳 + 数字)
xaplux
2022-05-24 16:29:00 +08:00
防止找规律的话,可以再加盐
zhengjian
2022-05-24 16:30:36 +08:00
learningman
2022-05-24 16:32:39 +08:00
"要不容易通过已知的几个(num, result)映射找出规律"
又想可逆又想不被破解,哪有那么好的事。B 站那个 AV BV 的转换都能被直接看出来怎么转换的
zhengjian
2022-05-24 16:36:33 +08:00
reply #8

```
# https://github.com/davidaurelio/hashids-python
from hashids import Hashids



hashids = Hashids(slat="blablablabla", min_length=8)
hashid = hashids.encode(1)
number = hashids.decode(hashid)

```
caqiko
2022-05-24 17:00:48 +08:00
@zhengjian 谢谢,这个方案最容易上手且满足需求
darkengine
2022-05-24 17:02:22 +08:00
从高位开始
第一位 0-9 从[0-9, A-Z] 随机挑选 10 个字符作为映射。
第二位 0-9 从[0-9, A-Z] 随机挑选 10 个字符作为映射。
第二位 0-9 从[0-9, A-Z] 随机挑选 10 个字符作为映射。
……
以此类推,最后两位可以把前面几位相加,得到的两位数再处理。要是嫌记每位 10 个字符的映射太麻烦,用 ASCII 码每位取不同的 offset 去映射也可以。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/854988

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX