Conversión base 62

92

¿Cómo convertiría un número entero a base 62 (como hexadecimal, pero con estos dígitos: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')?

He estado tratando de encontrar una buena biblioteca de Python para ello, pero todos parecen estar ocupados con la conversión de cadenas. El módulo Python base64 solo acepta cadenas y convierte un solo dígito en cuatro caracteres. Estaba buscando algo parecido a lo que usan los acortadores de URL.

mikl
fuente
Parece que alguien acaba de encontrar una idea de proyecto de código abierto :) Avísame si encuentras algo o decides crear el tuyo propio ...
samoz
Si desea crear URL cortas, es posible que desee utilizar todo el conjunto de caracteres que no es necesario codificar: en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . Eso es 66 caracteres.
l0b0
Creo que pasaré el punto y la tilde, solo para evitar la confusión del usuario, pero el guión y los guiones bajos deberían ser adiciones valiosas, gracias.
mikl
¿Qué pasa con Base64? Puede que tengas más suerte encontrando bibliotecas para eso.
Mike Cooper
Esta pregunta tiene varias respuestas aplicables: stackoverflow.com/questions/561486/…
Miles

Respuestas:

169

No hay un módulo estándar para esto, pero he escrito mis propias funciones para lograrlo.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def encode(num, alphabet):
    """Encode a positive number into Base X and return the string.

    Arguments:
    - `num`: The number to encode
    - `alphabet`: The alphabet to use for encoding
    """
    if num == 0:
        return alphabet[0]
    arr = []
    arr_append = arr.append  # Extract bound-method for faster access.
    _divmod = divmod  # Access to locals is faster.
    base = len(alphabet)
    while num:
        num, rem = _divmod(num, base)
        arr_append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def decode(string, alphabet=BASE62):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for decoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

Observe el hecho de que puede asignarle cualquier alfabeto para codificar y decodificar. Si omite el alphabetargumento, obtendrá el alfabeto de 62 caracteres definido en la primera línea de código y, por lo tanto, codificará / decodificará a / desde la base 62.

Espero que esto ayude.

PD: para los acortadores de URL, he descubierto que es mejor omitir algunos caracteres confusos como 0Ol1oI, etc. Por lo tanto, utilizo este alfabeto para mis necesidades de acortamiento de URL. "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

Que te diviertas.

Baishampayan Ghose
fuente
5
+1: ¡Bien! Esto se puede ampliar con más caracteres compatibles con URL para posiblemente guardar un carácter aquí y allá. Los personajes que sé que son seguros son: $-_.+!*'(),;/?:@&= Probablemente puedas usar otros personajes como, []~etc.
Blixt
24
Error de nomenclatura: no es la base 62, ya que el alfabeto es personalizable.
relajarse
3
Para la decodificación, es un mejor hábito no calcular las potencias (ahorra tiempo, es más corto de escribir, pero lo que es más importante evita errores de uno en uno), así: num = 0; para char en cadena: num = num * base + alphabet.index (char)
ShreevatsaR
1
@ShreevatsaR: ¿alguna razón particular para usar str.index () en lugar de una búsqueda en el diccionario? Vea mi respuesta ...
John Machin
2
Jonathan - Python puede manejar números de longitud arbitraria - no hay desbordamiento: >>> 256 * (62 ** 100) 44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256L
Anthony Briggs
53

Una vez escribí un guión para hacer esto también, creo que es bastante elegante :)

import string
# Remove the `_@` below for base62, now it has 64 characters
BASE_LIST = string.digits + string.letters + '_@'
BASE_DICT = dict((c, i) for i, c in enumerate(BASE_LIST))

def base_decode(string, reverse_base=BASE_DICT):
    length = len(reverse_base)
    ret = 0
    for i, c in enumerate(string[::-1]):
        ret += (length ** i) * reverse_base[c]

    return ret

def base_encode(integer, base=BASE_LIST):
    if integer == 0:
        return base[0]

    length = len(base)
    ret = ''
    while integer != 0:
        ret = base[integer % length] + ret
        integer /= length

    return ret

Uso de ejemplo:

for i in range(100):                                    
    print i, base_decode(base_encode(i)), base_encode(i)
Wolph
fuente
9
Esta versión es considerablemente más rápida que la solución aceptada de Baishampayan. Optimicé aún más calculando la longitud fuera de la función. Resultados de las pruebas (100.000 iteraciones): versión WoLpH: .403 .399 .399 .398 .398 | versión-Baishampayan: 1.783 1.785 1.782 1.788 1.784. Esta versión es aproximadamente 4 veces más rápida.
Jordania
si se usa reversed(string)más rápido que cortar string[::-1]en la función base_decode.
ENDOH takanao
1
Me tomó mucho tiempo encontrar esta pregunta. Nunca supe que esto se llamaba conversión base62. Buena respuesta.
1
Tuve que cambiar integer /= lengtha integer //=lengthpara obtener el resto correcto
karlgold
10

El siguiente creador de decodificadores funciona con cualquier base razonable, tiene un bucle mucho más ordenado y da un mensaje de error explícito cuando encuentra un carácter no válido.

def base_n_decoder(alphabet):
    """Return a decoder for a base-n encoded string
    Argument:
    - `alphabet`: The alphabet used for encoding
    """
    base = len(alphabet)
    char_value = dict(((c, v) for v, c in enumerate(alphabet)))
    def f(string):
        num = 0
        try:
            for char in string:
                num = num * base + char_value[char]
        except KeyError:
            raise ValueError('Unexpected character %r' % char)
        return num
    return f

if __name__ == "__main__":
    func = base_n_decoder('0123456789abcdef')
    for test in ('0', 'f', '2020', 'ffff', 'abqdef'):
        print test
        print func(test)
John Machin
fuente
Si bien probablemente nunca usaría esto, también te había dado el visto bueno a la creatividad. Este código me hizo reír. :)
Sepero
@Sepero: ¿Qué es tan gracioso? Es un software serio y robusto de potencia industrial. No hay marcha atrás de Micky-Mouse con un **operador en el bucle.
John Machin
Cálmate amigo. Tienes razón. Me perdí la verdadera bondad de su bucle interno debido a que está enterrado dentro de cosas que no están relacionadas con la pregunta (envoltura, verificación de errores, prueba unitaria).
Sepero
Se ve bien, pero ¿no se ha olvidado de un codificador de "potencia industrial" que necesita un número entero más el alfabeto para producir una cadena?
martineau
1
¿Fue la q en el último valor intencional para mostrar el ValueError que se generó?
Thomas Vander Stichele
8

Si está buscando la mayor eficiencia (como django), querrá algo como lo siguiente. Este código es una combinación de métodos eficientes de Baishampayan Ghose y WoLpH y John Machin.

# Edit this list of characters as desired.
BASE_ALPH = tuple("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))
BASE_LEN = len(BASE_ALPH)

def base_decode(string):
    num = 0
    for char in string:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def base_encode(num):
    if not num:
        return BASE_ALPH[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding = BASE_ALPH[rem] + encoding
    return encoding

Es posible que también desee calcular su diccionario por adelantado. (Nota: la codificación con una cadena muestra más eficiencia que con una lista, incluso con números muy largos).

>>> timeit.timeit("for i in xrange(1000000): base.base_decode(base.base_encode(i))", setup="import base", number=1)
2.3302059173583984

Codificó y descodificó 1 millón de números en menos de 2,5 segundos. (2,2 Ghz i7-2670QM)

Sepero
fuente
Uno no necesita necesariamente estar tuple()alrededor BASE_ALPHal principio. En Python, cada cadena es iterable. Por supuesto, esa característica es explotada por enumerate(). Entonces el código se vuelve aún más ágil :)
Luis Nell
7
Oye, origiNell, tienes razón en que la tupla () no es necesaria, pero en mi sistema, hace que el código se ejecute un 20% más rápido. Intente probarlo sin la tupla () y vea qué funciona mejor para usted. Saludos :)
Sepero
1
Interesante punto. Tiene mucho sentido ya que las tuplas son más ligeras que las cadenas. ¡Gracias por la iluminación :)!
Luis Nell
@Sepero Mejoré aún más su versión en términos de formato, nombres, pruebas y funcionalidad (se admiten números negativos): pastebin.com/4uket7iu (puede actualizar su respuesta con esto)
Joschua
@Joschua - Tu código en tu URL no funcionó para mí. base_encode () parecía generar solo un dígito codificado para los números que probé.
SMGreenfield
4

Si todo lo que necesita es generar una ID corta (ya que menciona acortadores de URL) en lugar de codificar / decodificar algo, este módulo podría ayudar:

https://github.com/stochastic-technologies/shortuuid/

Stavros Korokithakis
fuente
No estoy seguro de que sea apropiado para URL cortas. Un UUID suele ser un número muy grande, por lo que incluso la codificación en base57 como él lo hace probablemente sea bastante larga para una URL corta.
mikl
Puede cortar todo lo que quiera, las colisiones seguirán siendo poco probables ya que es puramente aleatorio, pero ya no será una identificación única.
Stavros Korokithakis
4

Si usa el framework django, puede usar el módulo django.utils.baseconv.

>>> from django.utils import baseconv
>>> baseconv.base62.encode(1234567890)
1LY7VK

Además de base62, baseconv también definió base2 / base16 / base36 / base56 / base64.

Ryan Fau
fuente
3

Probablemente quieras base64, no base62. Hay una versión compatible con URL flotando, por lo que los dos caracteres de relleno adicionales no deberían ser un problema.

El proceso es bastante simple; considere que base64 representa 6 bits y un byte regular representa 8. Asigne un valor de 000000 a 111111 a cada uno de los 64 caracteres elegidos y coloque los 4 valores juntos para que coincidan con un conjunto de 3 base256 bytes. Repita para cada conjunto de 3 bytes, rellenando al final con su elección de carácter de relleno (0 es generalmente útil).

Williham Totland
fuente
5
Los métodos de codificación estándar de Python base64 no son realmente adecuados para URL cortas, ya que están optimizados para codificar bytes (es decir, cadenas / letras) y producirán resultados más largos que simplemente cambiar la base del valor numérico.
mikl
@mikl Por supuesto, el módulo base64 de Python puede no ser adecuado para generar URL cortas, pero todos los métodos de codificación de Python realmente funcionan en secuencias numéricas de base 256. los bytes son realmente "cadenas" codificadas en base 256. Python 2.x trata las cadenas como una secuencia de bytes, mientras que Python 3.x (que hace lo correcto) trata las cadenas como Unicode. Entonces, b'foobar 'es realmente solo una forma elegante de escribir [102, 111, 111, 98, 97, 114] o [0x66,0x6f, 0x6f, 0x62,0x61,0x72] o b' \ x66 \ x6f \ x6f \ x62 \ x61 \ x72 'que, como era de esperar, es la representación en base 256. Los bytes no son cadenas ni letras. Los bytes son bytes. =)
yesudeep
@yesudeep: Entonces, los bytes son bytes ... ¿y cuál es exactamente tu punto?
martineau
3

Ahora hay una biblioteca de Python para esto.

Estoy trabajando en hacer un paquete de pip para esto.

Te recomiendo que uses mi bases.py https://github.com/kamijoutouma/bases.py que se inspiró en bases.js

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

consulte https://github.com/kamijoutouma/bases.py#known-basesalphabets para saber qué bases son utilizables

Belldandu
fuente
2

puede descargar el módulo zbase62 de pypi

p.ej

>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'
ghostdog74
fuente
2
Sí, lo miré antes, pero convierte cadenas, no números :)
mikl
2

Me he beneficiado enormemente de las publicaciones de otros aquí. Necesitaba el código de Python originalmente para un proyecto de Django, pero desde entonces he recurrido a node.js, así que aquí hay una versión javascript del código (la parte de codificación) que proporcionó Baishampayan Ghose.

var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

function base62_encode(n, alpha) {
  var num = n || 0;
  var alphabet = alpha || ALPHABET;

  if (num == 0) return alphabet[0];
  var arr = [];
  var base = alphabet.length;

  while(num) {
    rem = num % base;
    num = (num - rem)/base;
    arr.push(alphabet.substring(rem,rem+1));
  }

  return arr.reverse().join('');
}

console.log(base62_encode(2390687438976, "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"));
Stephen
fuente
Actualicé
Stephen
2

Espero que el siguiente fragmento pueda ayudar.

def num2sym(num, sym, join_symbol=''):
    if num == 0:
        return sym[0]
    if num < 0 or type(num) not in (int, long):
        raise ValueError('num must be positive integer')

    l = len(sym)  # target number base
    r = []
    div = num
    while div != 0: # base conversion
        div, mod = divmod(div, l)
        r.append(sym[mod])

    return join_symbol.join([x for x in reversed(r)])

Uso para su caso:

number = 367891
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
print num2sym(number, alphabet)  # will print '1xHJ'

Obviamente, puede especificar otro alfabeto, que consiste en un número mayor o menor de símbolos, luego convertirá su número a la base numérica mayor o menor. Por ejemplo, al proporcionar '01' como un alfabeto, se generará una cadena que representa el número de entrada como binario.

Puede mezclar el alfabeto inicialmente para tener su representación única de los números. Puede ser útil si está creando un servicio de acortador de URL.

Vladimir Ignatyev
fuente
1
No está mal. Es posible que desee utilizar if num < 0 or type(num) not in (int, long):.
Martineau
Eso es mejor, pero es un poco más complicado porque longno existe en Py 3.x, por lo que es posible que desee usar esta respuesta .
Martineau
1
O usar mi propia versión portátil: isinstance(x, (type(1), type(2**32))).
Martineau
2

Esta es mi solución:

def base62(a):
    baseit = (lambda a=a, b=62: (not a) and '0' or
        baseit(a-a%b, b*62) + '0123456789abcdefghijklmnopqrstuvwxyz'
                              'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%b%61 or -1*bool(a%b)])
    return baseit()

explicación

En cualquier base, cada número es igual a a1+a2*base**2+a3*base**3...Entonces, el objetivo es encontrar todas las as.

Por cada N=1,2,3...código aísla el aN*base**Nde "moduloing" por bpara b=base**(N+1)que corta todo aes más grande que N, y cortar toda la as por lo que su serie es menor que Nal disminuir acada vez que la función se llama de forma recursiva por la corriente aN*base**N.

Base%(base-1)==1por base**p%(base-1)==1lo tanto y por lo tanto q*base^p%(base-1)==qcon una sola excepción, cuando q==base-1regresa 0. Para arreglar ese caso, vuelve 0. La función busca 0desde el principio.


ventajas

En esta muestra, solo hay una multiplicación (en lugar de una división) y algunas operaciones de módulo, que son todas relativamente rápidas.

Shu ba
fuente
1

Personalmente, me gusta la solución de Baishampayan, principalmente porque quita los confusos personajes.

Para mayor integridad y solución con mejor rendimiento, esta publicación muestra una forma de usar el módulo Python base64.

Van Gale
fuente
1
Como mencioné en mi comentario a Williham Totland, Pythons base64 no es óptimo para codificar números, ya que está optimizado para cadenas.
mikl
1

Escribí esto hace un tiempo y funcionó bastante bien (negativos y todo incluido)

def code(number,base):
    try:
        int(number),int(base)
    except ValueError:
        raise ValueError('code(number,base): number and base must be in base10')
    else:
        number,base = int(number),int(base)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = [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"]
    final = ""
    loc = 0
    if number < 0:
        final = "-"
        number = abs(number)
    while base**loc <= number:
        loc = loc + 1
    for x in range(loc-1,-1,-1):
        for y in range(base-1,-1,-1):
            if y*(base**x) <= number:
                final = "{}{}".format(final,numbers[y])
                number = number - y*(base**x)
                break
    return final

def decode(number,base):
    try:
        int(base)
    except ValueError:
        raise ValueError('decode(value,base): base must be in base10')
    else:
        base = int(base)
    number = str(number)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = ["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"]
    final = 0
    if number.startswith("-"):
        neg = True
        number = list(number)
        del(number[0])
        temp = number
        number = ""
        for x in temp:
            number = "{}{}".format(number,x)
    else:
        neg = False
    loc = len(number)-1
    number = str(number)
    for x in number:
        if numbers.index(x) > base:
            raise ValueError('{} is out of base{} range'.format(x,str(base)))
        final = final+(numbers.index(x)*(base**loc))
        loc = loc - 1
    if neg:
        return -final
    else:
        return final

perdón por la duración de todo

Trópico
fuente
1
BASE_LIST = tuple("23456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_LIST))
BASE_LEN = len(BASE_LIST)

def nice_decode(str):
    num = 0
    for char in str[::-1]:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def nice_encode(num):
    if not num:
        return BASE_LIST[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding += BASE_LIST[rem]
    return encoding
paulkav1
fuente
1
Esto corrige el nombre de BASE_LIST y también invierte la cadena en la decodificación que se omitió en la excelente respuesta de
Spero
1

Aquí hay una forma repetitiva e iterativa de hacerlo. El iterativo es un poco más rápido dependiendo del conteo de ejecución.

def base62_encode_r(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return s[dec] if dec < 62 else base62_encode_r(dec / 62) + s[dec % 62]
print base62_encode_r(2347878234)

def base62_encode_i(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = ''
    while dec > 0:
        ret = s[dec % 62] + ret
        dec /= 62
    return ret
print base62_encode_i(2347878234)

def base62_decode_r(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if len(b62) == 1:
        return s.index(b62)
    x = base62_decode_r(b62[:-1]) * 62 + s.index(b62[-1:]) % 62
    return x
print base62_decode_r("2yTsnM")

def base62_decode_i(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = 0
    for i in xrange(len(b62)-1,-1,-1):
        ret = ret + s.index(b62[i]) * (62**(len(b62)-i-1))
    return ret
print base62_decode_i("2yTsnM")

if __name__ == '__main__':
    import timeit
    print(timeit.timeit(stmt="base62_encode_r(2347878234)", setup="from __main__ import base62_encode_r", number=100000))
    print(timeit.timeit(stmt="base62_encode_i(2347878234)", setup="from __main__ import base62_encode_i", number=100000))
    print(timeit.timeit(stmt="base62_decode_r('2yTsnM')", setup="from __main__ import base62_decode_r", number=100000))
    print(timeit.timeit(stmt="base62_decode_i('2yTsnM')", setup="from __main__ import base62_decode_i", number=100000))

0.270266867033
0.260915645986
0.344734796766
0.311662500262
Wenzul
fuente
Realmente me gustó tu enfoque recursivo. Mi hija, que estaba tomando AP Comp Sci, había descubierto esta misma solución para que yo implemente una "base25" (usando 'ABCDEFHJKMNPQRTUVWXY34789') en C ++. Fui a convertirlo a Python y siendo un novato total con ese lenguaje, encontré algunos obstáculos, ¡que resolviste elegantemente en una sola línea de código! Incluso evita un problema común con 0 que se traduce en una cadena vacía en alfabetos que no comienzan con 0-9. ¡Buen trabajo! (No necesito números negativos, pero su enfoque fue tan bueno que podría ser bueno agregar eso para futuros navegadores)
SMGreenfield
1

Pitón 3.7.x

Encontré un github de doctorado para algunos algoritmos cuando buscaba un script base62 existente . No funcionó para la versión máxima actual de Python 3 en este momento, así que seguí adelante y lo arreglé donde era necesario e hice una pequeña refactorización. No suelo trabajar con Python y siempre lo he usado ad-hoc, así que YMMV. Todo el mérito es para el Dr. Zhihua Lai . Acabo de resolver los problemas para esta versión de Python.

archivo base62.py

#modified from Dr. Zhihua Lai's original on GitHub
from math import floor
base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
b = 62;
def toBase10(b62: str) -> int:
    limit = len(b62)
    res = 0
    for i in range(limit):
        res = b * res + base.find(b62[i])
    return res
def toBase62(b10: int) -> str:
    if b <= 0 or b > 62:
        return 0
    r = b10 % b
    res = base[r];
    q = floor(b10 / b)
    while q:
        r = q % b
        q = floor(q / b)
        res = base[int(r)] + res
    return res

archivo try_base62.py

import base62
print("Base10 ==> Base62")
for i in range(999):
    print(f'{i} => {base62.toBase62(i)}')
base62_samples = ["gud", "GA", "mE", "lo", "lz", "OMFGWTFLMFAOENCODING"]
print("Base62 ==> Base10")
for i in range(len(base62_samples)):
    print(f'{base62_samples[i]} => {base62.toBase10(base62_samples[i])}')

salida de try_base62.py

Base10 ==> Base62
0 => 0
[...]
998 => g6
Base62 ==> Base10
gud => 63377
GA => 2640
mE => 1404
lo => 1326
lz => 1337
OMFGWTFLMFAOENCODING => 577002768656147353068189971419611424

Como no había información de licencia en el repositorio, envié un PR para que el autor original al menos sepa que otras personas están usando y modificando su código.

kayleeFrye_onDeck
fuente
0

Lo siento, no puedo ayudarte con una biblioteca aquí. Preferiría usar base64 y simplemente agregar caracteres adicionales a su elección, ¡si es posible!

Entonces puedes usar el módulo base64.

Si esto es realmente imposible:

Puede hacerlo usted mismo de esta manera (esto es un pseudocódigo):

base62vals = []
myBase = 62
while num > 0:
   reminder = num % myBase
   num = num / myBase
   base62vals.insert(0, reminder)
Juergen
fuente
0

con recursividad simple

"""
This module contains functions to transform a number to string and vice-versa
"""
BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
LEN_BASE = len(BASE)


def encode(num):
    """
    This function encodes the given number into alpha numeric string
    """

    if num < LEN_BASE:
        return BASE[num]

    return BASE[num % LEN_BASE] + encode(num//LEN_BASE)


def decode_recursive(string, index):
    """
    recursive util function for decode
    """

    if not string or index >= len(string):
        return 0

    return (BASE.index(string[index]) * LEN_BASE ** index) + decode_recursive(string, index + 1)


def decode(string):
    """
    This function decodes given string to number
    """

    return decode_recursive(string, 0)

Lokesh Sanapalli
fuente
0

El más simple de todos.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode_base62(num):
    s = ""
    while num>0:
      num,r = divmod(num,62)
      s = BASE62[r]+s
    return s


def decode_base62(num):
   x,s = 1,0
   for i in range(len(num)-1,-1,-1):
      s = int(BASE62.index(num[i])) *x + s
      x*=62
   return s

print(encode_base62(123))
print(decode_base62("1Z"))
melvil james
fuente