#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'))
и подтвердил, что он ничего не печатает.
Ответ №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
forabc('?-2-3-9-0')
3. Это решение было дано до того, как автор добавил новую идею о ‘?-3-4’. И прежде чем он ограничит использование словарей.