Как преобразовать целое число в самую короткую безопасную от URL строку в Python?

Вы можете попробовать это:

DA-ENERGY-OFFERS-\d+.csv

Примерно так:

list.files(path="ftp://pubftp.spp.org/Markets/HistoricalOffers/2014", pattern="DA-ENERGY-OFFERS-\d+.csv", recursive = TRUE, full.names = TRUE)

Как показано здесь: https://regex101.com/r/ cYM9lT / 2

Что касается ошибки, в которой был ваш код, то вы неправильно использовали классы символов. [...] соответствует одному из символов в [], а не всей строке. Пример: [abcd] будет соответствовать каждому отдельному символу в нем, то есть 'a', 'b', 'c' и 'd'

Использование его с - подразумевает любой символ в этом диапазоне
Пример: [a-h] будет соответствовать каждому отдельному символу в пределах диапазона «a» и «h» (включительно). В вашем коде, когда регулярное выражение встречает R-O внутри класса символов, оно сбивается с толку, потому что нет правильного ответа для R-O. Отсюда и ошибка в паттерне.

63
задан user000001 21 September 2013 в 16:09
поделиться

9 ответов

Этот ответ подобен в духе Douglas Leeder со следующими изменениями:

  • Это не использует фактический Base64, таким образом, нет никаких дополнительных символов
  • Вместо того, чтобы преобразовать число сначала в строку байтов (базируются 256), это преобразовывает его непосредственно для базирования 64, который имеет преимущество разрешения Вам представить отрицательные числа с помощью символа знака.

    import string
    ALPHABET = string.ascii_uppercase + string.ascii_lowercase + \
               string.digits + '-_'
    ALPHABET_REVERSE = dict((c, i) for (i, c) in enumerate(ALPHABET))
    BASE = len(ALPHABET)
    SIGN_CHARACTER = '$'
    
    def num_encode(n):
        if n < 0:
            return SIGN_CHARACTER + num_encode(-n)
        s = []
        while True:
            n, r = divmod(n, BASE)
            s.append(ALPHABET[r])
            if n == 0: break
        return ''.join(reversed(s))
    
    def num_decode(s):
        if s[0] == SIGN_CHARACTER:
            return -num_decode(s[1:])
        n = 0
        for c in s:
            n = n * BASE + ALPHABET_REVERSE[c]
        return n
    

    >>> num_encode(0)
    'A'
    >>> num_encode(64)
    'BA'
    >>> num_encode(-(64**5-1))
    '$_____'

Несколько примечаний стороны:

  • Вы могли (незначительно) увеличить человека-readibility основы 64 числа путем помещения string.digits сначала в алфавит (и создания символа знака '-'); я выбрал порядок, который я сделал на основе Python urlsafe_b64encode.
  • При кодировании большого количества отрицательных чисел Вы могли бы увеличить эффективность при помощи знакового бита или дополнения one's/two вместо символа знака.
  • Необходимо смочь легко адаптировать этот код к различным основаниям путем изменения алфавита, или ограничить его только алфавитно-цифровыми символами или добавить дополнительные символы "URL-safe".
  • Я рекомендовал бы против использования представления кроме основы 10 в URIs в большинстве случаев — это добавляет сложность и делает отладку тяжелее без значительных сбережений по сравнению с издержками HTTP — если Вы не идете для чего-то TinyURL-esque.
60
ответ дан Miles 24 November 2019 в 16:16
поделиться

Я пошел бы, 'кодируют целое число двоичной строкой, затем base64 кодируют тот' метод, который Вы предлагаете, и я сделал бы это с помощью структуры:

>>> import struct, base64
>>> base64.b64encode(struct.pack('l', 47))
'LwAAAA=='
>>> struct.unpack('l', base64.b64decode(_))
(47,)

Редактирование снова: Для разделения дополнительного 0s на числах, которые являются слишком небольшими для необходимости в полной 32-разрядной точности попробуйте это:

def pad(str, l=4):
    while len(str) < l:
        str = '\x00' + str
    return str

>>> base64.b64encode(struct.pack('!l', 47).replace('\x00', ''))
'Lw=='
>>> struct.unpack('!l', pad(base64.b64decode('Lw==')))
(47,)
1
ответ дан GEOCHET 24 November 2019 в 16:16
поделиться

Если Вы ищете путь к , сокращаются целочисленное представление с помощью base64, я думаю, что необходимо посмотреть в другом месте. При кодировании чего-то base64, это не становится короче, на самом деле это становится длиннее.

, Например, 11 234 закодированных с base64 привел бы к MTEyMzQ =

При использовании base64, Вы пропустили то, что Вы не преобразовываете просто цифры (0-9) в 64 кодировки символов. Вы преобразовываете 3 байта в 4 байта, таким образом, Вам гарантируют Ваш base64, закодированная строка была бы на 33,33% длиннее.

2
ответ дан Sergey Golovchenko 24 November 2019 в 16:16
поделиться

немного hacky, но это работает:

def b64num(num_to_encode):
  h = hex(num_to_encode)[2:]     # hex(n) returns 0xhh, strip off the 0x
  h = len(h) & 1 and '0'+h or h  # if odd number of digits, prepend '0' which hex codec requires
  return h.decode('hex').encode('base64') 

Вы могли заменить вызов к .encode ('base64') с чем-то в base64 модуле, таком как urlsafe_b64encode ()

3
ответ дан ʞɔıu 24 November 2019 в 16:16
поделиться

Вы не хотите кодирование base64, Вы хотите представить основу, которую 10 цифр в цифре основывают X.

, Если Вы хотите свою базу 10 цифр, представленных в 26 буквах, доступных, Вы могли бы использовать: http://en.wikipedia.org/wiki/Hexavigesimal . (Можно расширить тот пример для намного большей основы при помощи всех легальных символов URL)

, необходимо по крайней мере смочь стать основными 38 (26 букв, 10 чисел, +, _)

7
ответ дан Øystein E. Krog 24 November 2019 в 16:16
поделиться

Легкий бит преобразовывает строку байтов в веб-безопасный base64:

import base64
output = base64.urlsafe_b64encode(s)

хитрый бит является первым шагом - преобразовывают целое число в строку байтов.

, Если Ваши целые числа являются маленькими, Вы - более обеспеченное шестнадцатеричное число, кодирующее их - см. saua

Иначе (hacky рекурсивная версия):

def convertIntToByteString(i):
    if i == 0:
        return ""
    else:
        return convertIntToByteString(i >> 8) + chr(i & 255)
8
ответ дан Community 24 November 2019 в 16:16
поделиться

Закодировать n:

data = ''
while n > 0:
    data = chr(n & 255) + data
    n = n >> 8
encoded = base64.urlsafe_b64encode(data).rstrip('=')

Для декодирования s:

data = base64.urlsafe_b64decode(s + '===')
decoded = 0
while len(data) > 0:
    decoded = (decoded << 8) | ord(data[0])
    data = data[1:]

В том же духе как другой для некоторого кодирования “optimal”, можно использовать 73 символы согласно RFC 1738 (на самом деле 74 при подсчете “+” как применимого):

alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_`\"! 

и декодирование:

decoded = 0
while len(s) > 0:
    decoded = decoded * len(alphabet) + alphabet.find(s[0])
    s = s[1:]
()*,-." encoded = '' while n > 0: n, r = divmod(n, len(alphabet)) encoded = alphabet[r] + encoded

и декодирование:

decoded = 0
while len(s) > 0:
    decoded = decoded * len(alphabet) + alphabet.find(s[0])
    s = s[1:]
9
ответ дан kmkaplan 24 November 2019 в 16:16
поделиться

Вы, вероятно, не хотите реальное кодирование base64 для этого - оно добавит дополнение и т.д., потенциально даже приводя к большим строкам, чем шестнадцатеричное число было бы для небольших чисел. Если нет никакой потребности взаимодействовать с чем-либо еще, просто используйте свое собственное кодирование. Например, вот функция, которая закодирует к любой основе (обратите внимание, что цифры на самом деле хранятся младшие значащие сначала для предотвращения дополнительного реверса () вызовы:

def make_encoder(baseString):
    size = len(baseString)
    d = dict((ch, i) for (i, ch) in enumerate(baseString)) # Map from char -> value
    if len(d) != size:
        raise Exception("Duplicate characters in encoding string")

    def encode(x):
        if x==0: return baseString[0]  # Only needed if don't want '' for 0
        l=[]
        while x>0:
            l.append(baseString[x % size])
            x //= size
        return ''.join(l)

    def decode(s):
        return sum(d[ch] * size**i for (i,ch) in enumerate(s))

    return encode, decode

# Base 64 version:
encode,decode = make_encoder("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")

assert decode(encode(435346456456)) == 435346456456

Это имеет преимущество, что можно использовать любую основу, которую Вы хотите, только путем добавления соответствующих символов к основной строке кодера.

Примечание, что усиления для больших оснований не будут этим большим как бы то ни было. основа 64 только уменьшит размер до 2/3rds основы 16 (6 битов/символы вместо 4). Каждое удвоение только добавляет еще один бит на символ. Если у Вас не будет реальной потребности уплотнить вещи, просто использование шестнадцатеричного числа, вероятно, будет самой простой и самой быстрой опцией.

14
ответ дан Brian 24 November 2019 в 16:16
поделиться

Base64 берет 4 байта/символы для кодирования 3 байтов и может только закодировать кратные числа 3 байтов (и добавляет дополнение иначе).

Настолько представляющие 4 байта (Ваш средний интервал) в Base64 взяли бы 8 байтов. Кодирование тех же 4 байтов в шестнадцатеричном числе также взяло бы 8 байтов. Таким образом, Вы ничего не получили бы для единственного интервала

4
ответ дан Joachim Sauer 24 November 2019 в 16:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: