Создание функции, которая преобразует число в букву

#python

#python

Вопрос:

Я написал эту функцию, которая должна проходить через предоставленную пользователем строку like 1-3-5 и выводить соответствующую серию букв, где A присваивается 1, B присваивается 2, C присваивается 3 и т.д. Так что в случае 1-3-5 вывода будет ACE . Для 2-3-4 этого он должен печатать BCD . Для ?-3-4 or --3-4 он все равно должен печатать BCD. Вот код, который я написал до сих пор:

 def number_to_letter(encoded):
    result = ""
    start = 0
    for char in range(len(encoded)):
        if encoded[char] == '-':
            i = encoded.index("-")
            sub_str = encoded[start:i]
            if not sub_str.isdigit():
                result  = ""
            else:
                letter = chr(64   int(sub_str))
                if 0 < int(sub_str) < 27:
                    result  = letter

                else:
                    result  = ""

            start  = len(sub_str)   1
    return result

print(num_to_let('4-3-25'))
  

Мой вывод D , когда это должно быть DCY . Я пытаюсь сделать это без использования каких-либо списков или с помощью split функции, просто найдя - символ в подстроке и преобразовав числа перед ним в букву. Что я могу сделать?

Комментарии:

1. Используйте encoded.split('-') вместо чтения посимвольно.

2. Извините, я должен был указать; Мне нужно сделать это без функции разделения. Я обновил исходное сообщение, чтобы отразить это.

3. Я бы предложил не использовать str в качестве имени переменной. str это очень простая встроенная функция, которую вам, возможно, очень нужно использовать, но вы не сможете, если вы локально переопределили ее.

4. @Carcigenicate я добавил print(number_to_letter('1-3-5')) и подтвердил, что он ничего не печатает.

5. ericlippert.com/2014/03/05/how-to-debug-small-programs

Ответ №1:

Вы можете попробовать сделать что-то вроде этого:

 def number_to_letter(encoded):
    result  = ""
    buffer = ""
    for ch in encoded:
        if ch == '-':
            if buffer and 0 < int(buffer) < 27:
                result  = chr(64   int(buffer))
            buffer = ""
        elif ch.isdigit():
            buffer  = ch
    else:
        if buffer and 0 < int(buffer) < 27:
            result  = chr(64   int(buffer))
        return result 

print(number_to_letter('1-3-5'))
  

вывод:

 ACE
  

Объяснение:

мы выполняем цикл для каждого символа и добавляем его в некоторый буфер. когда мы сталкиваемся - с (разделителем), мы пытаемся проанализировать буфер и сбросить его. И мы делаем тот же синтаксический анализ в конце еще раз и возвращаем результат.

Способ проверки заключается в том, что всякий раз, когда мы заполняем буфер, мы проверяем правильность числа (используя .isdigit() ), и когда мы анализируем буфер, мы проверяем ограничения диапазона.

Комментарии:

1. Это очень полезно — большое спасибо! В моей оригинальной программе я учитывал нечисловой ввод или числа, которые были меньше 0 или больше 26. Смогу ли я сделать то же самое в предоставленном вами коде?

2. @AnthonyPetruzzio Вот так! 🙂

3. Я не совсем понимаю, для какой цели служит buffer или почему работает int(buffer). Разве buffer не строка? Не могли бы вы объяснить это немного подробнее?

4. @AnthonyPetruzzio конечно. поскольку мы работаем с циклом for (char-by-char), нам нужно некоторое временное свободное пространство, в котором мы могли бы накапливать символы.

5. и когда мы сталкиваемся с '-' , мы пытаемся проанализировать данные, которые мы накопили там => добавить к результату => и, наконец, сбросить эту переменную

Ответ №2:

 import string

alphabet = list(string.ascii_lowercase)
combination = "1-2-3"

def seperate(s, sep='-'):
    return [s[:s.index(sep)]]   seperate(s[s.index(sep) 1:]) if sep in s else [s]

combination = seperate(combination)

print("".join([alphabet[int(i)-1] for i in combination]))
  

Комментарии:

1. Он отредактировал вопрос, чтобы сказать, что он не хочет использовать split()

2. о боже … почему

Ответ №3:

подход этого кода заключается в том, чтобы найти первый ‘-‘, а затем сохранить, где он находится, чтобы в следующий раз мы могли искать первый ‘-‘ после последнего

когда в комментариях в моем коде говорится о цикле, это означает прохождение цикла (во время цикла:) один раз

 def number_to_letter(encoded):
    letterString = ""
    startSubStr = 0
    endSubStr = 0
    looping = True

    while looping:
        if endSubStr > (len(encoded)-4):# if we're at the last number we don't look for '-'. we go to the end of the str and end the loop
            endSubStr = len(encoded)
            looping = False
        else:
            endSubStr = encoded.index('-', startSubStr) #find the first '-' after the '-' found in the last cycle

        number = int(encoded[startSubStr:endSubStr]) #get the number between the '-' found in the last cycle through this loop and the '-' found in this one
        if number < 27:
            letter = chr(64   int(number))
            letterString  = letter

        startSubStr = endSubStr   1 #set the start of the substring to the end so the index function doesn't find the '-' found in this cycle again 

    return letterString

print(number_to_letter("23-1-1-2")) #>>> WAAB
  

Результат:
WAAB

Комментарии:

1. Могу ли я спросить, почему вы решили вычесть 4 в первом операторе if?

2. чтобы проверить, приближаюсь ли я к концу строки, если да, то при попытке найти следующий ‘-‘ возникнет ошибка, потому что в конце строки нет ‘-‘. endSubStr теперь устанавливается в фактический конец строки

3. @Jorrit200 Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.

4. @DevCl9 спасибо за ваш отзыв. Я добавлю некоторые комментарии к своему коду в ближайшем будущем. и общее описание к этому awnser.

Ответ №4:

Я вижу, вы не хотите использовать split , как насчет filter ? 😉

 import itertools

s = '1-2-3'
values = [''.join(e) for e in filter(
     lambda l: l != ['-'],
     [list(g) for k, g in itertools.groupby(
         [*s], lambda s: s.isnumeric()
        )
      ]
    )
]
  

Это, по сути, будет делать то, что .split('-') делает on s . Также list(s) будет вести себя так же, как [*s] если бы вы хотели использовать это вместо этого.

Теперь вы можете просто использовать ord и chr для построения требуемой строки-

 start_pivot = ord('A') - 1
res = ''.join([chr(int(i)   start_pivot) for i in values])
  

Вывод

 >>> s = '2-3-4'
>>> values = [''.join(e) for e in filter(
...:      lambda l: l != ['-'],
...:      [list(g) for k, g in itertools.groupby(
...:          [*s], lambda s: s.isnumeric()
...:         )
...:       ]
...:     )
...: ]
>>> start_pivot = ord('A') - 1
>>> res = ''.join([chr(int(i)   start_pivot) for i in values])
>>> res
'BCD'
  

Комментарии:

1. Это решение не допускает 2-значных чисел, например 12-3 , должно выдавать LC

2. @Barmar о, я этого не заметил, теперь это должно быть исправлено

3. «Я пытаюсь сделать это без использования каких-либо списков или …»

Ответ №5:

Нет списков, нет диктовок. Как насчет регулярного выражения?

 import re

def get_letter(n):
    if int(n) in range(1,27): return chr(int(n) 64)

def number_to_letter(s):
    return re.sub(r'd ', lambda x: get_letter(x.group()), s).replace('-','')

print(number_to_letter('1-2-26')) # Output: ABZ
  

Комментарии:

1. @Yuri Khristich ваше решение не подходит для нечисловых символов (на самом деле это довольно противоречиво). попробуйте «?-3-4 или —3-4 он все равно должен печатать BCD» (двойной sic!)! кстати, почему вы используете range ? разве это не итерируемо?

2. Я думаю, нам не нужно воспринимать эту проблему слишком серьезно. Автор, очевидно, имеет очень смутное представление о том, что он делает. Мое решение игнорирует эти ‘?-3-4’, ‘—3-4’ и т.д. Ваше решение выдает ошибку и падает. Что касается range , что вы имеете в виду? Он просто проверяет n , принадлежит ли (заданное число) диапазону от 1 до 26, или если оно меньше 26 и больше 0. Его также можно заменить этим 0 < n < 27 .

Ответ №6:

Никаких списков, хорошо. Но как насчет dicts?

 def abc(nums):
    d = {'-':'','1':'A','2':'B','3':'C','4':'D','5':'E','6':'F','7':'G','8':'H','9':'I','0':'J'}
    res = ''
    for n in nums: res  = d[n]
    return res
    
print(abc('1-2-3-9-0')) # Output: ABCIJ
  

Вот исправленная версия:

 def abc(nums):
    d = {'-':'','1':'A','2':'B','3':'C','4':'D','5':'E','6':'F','7':'G','8':'H','9':'I','0':'J'}
    res = ''
    for n in nums:
        if n in d:
            res  = d[n]
    return res

print(abc('?-2-3-9-0')) # Output: BCIJ
  

Комментарии:

1. Мне не разрешено использовать dicts.

2. это просто прямолинейно с KeyError for abc('?-2-3-9-0')

3. Это решение было дано до того, как автор добавил новую идею о ‘?-3-4’. И прежде чем он ограничит использование словарей.