V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
caqiko
V2EX  ›  Python

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

  •  
  •   caqiko · 2022-05-24 16:14:22 +08:00 · 1633 次点击
    这是一个创建于 674 天前的主题,其中的信息可能已经有所发展或是发生改变。
    # 对于任意一个 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 ,很不优雅
    不知道大佬们有没有什么好的思路?

    ChoateYao
        1
    ChoateYao  
       2022-05-24 16:16:51 +08:00   ❤️ 1
    这不就是 36 进制嘛
    sujin190
        2
    sujin190  
       2022-05-24 16:24:07 +08:00   ❤️ 1
    字母数字转化为 charCode 之后就是连续的数字了,查一下 base64 的编码算法照着写一个 base36 就是了呗
    liuidetmks
        3
    liuidetmks  
       2022-05-24 16:27:35 +08:00   ❤️ 1
    @sujin190 base36 可麻烦多了,做 base32 会简单很多,正好去掉一些容易混淆的. l1 0O
    xaplux
        4
    xaplux  
       2022-05-24 16:28:07 +08:00
    找一个基准时间戳,36 进制(基准时间戳 + 数字)
    xaplux
        5
    xaplux  
       2022-05-24 16:29:00 +08:00   ❤️ 1
    防止找规律的话,可以再加盐
    zhengjian
        6
    zhengjian  
       2022-05-24 16:30:36 +08:00   ❤️ 1
    learningman
        7
    learningman  
       2022-05-24 16:32:39 +08:00   ❤️ 1
    "要不容易通过已知的几个(num, result)映射找出规律"
    又想可逆又想不被破解,哪有那么好的事。B 站那个 AV BV 的转换都能被直接看出来怎么转换的
    zhengjian
        8
    zhengjian  
       2022-05-24 16:36:33 +08:00   ❤️ 1
    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
        9
    caqiko  
    OP
       2022-05-24 17:00:48 +08:00
    @zhengjian 谢谢,这个方案最容易上手且满足需求
    darkengine
        10
    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 去映射也可以。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3117 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 74ms · UTC 00:35 · PVG 08:35 · LAX 17:35 · JFK 20:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.