Python. Преобразование диапазонов чисел в список строк с маской
Прошу помощи сообщества в написании скрипта на python для решения следующией на первый взгляд не сложной задачи. Имеется входны данные диапазонов номеров телефонов и их принадлежности к часовой зоне - порядка 8000 строк. Пример значений:
От, До, Часовая зона
9000000000,9000000999,GMT+03:00
9010001000,9000002999,GMT+05:00
Необходимо на выходе получить набор строковых значений вида:
9000000XXX,GMT+03:00
9010001XXX,GMT+05:00
9010002XXX,GMT+05:00
Под такие ровные дапазоны скрипт получился очень простой и рабочий:
def getLength(value: int): # определяю количество разрядов, которые делятся на 10 без остатка
count = 0
while not value % 10:
value //= 10
count += 1
return count
def createAndSend(lstFrom, lstTo, mask, timeZone, title): # Формирование строки по маске
while lstFrom <= lstTo:
code = (str(lstFrom)+mask)
lstFrom += 1
lstOut.append({"Шаблон номера телефона": code, "Часовой пояс": timeZone})
return lstOut
for i in lstIn:
elem1 = int(i[0]) # Первый номер диапазона
elem2 = int(i[1]) # Последний номер диапазона
timeZone = i[2] # Часовая зона
qnty = elem2 - elem1 + 1 # Емкость. Можно сразу работать с диапазоном csv, но вдруг будет другая БД
length = getLength(qnty) # Получаем количество разрядов, которое можно заменить маской "Х"
if length == 1:
mask=''
elif length == 2:
mask='X'
elif length == 3:
mask='XX'
elif length == 4:
mask='XXX'
elif length == 5:
mask='XXXX'
elif length == 6:
mask='XXXXX'
elif length == 7:
mask='XXXXXX'
elif length == 8:
mask='XXXXXXX'
elif length == 9:
mask='XXXXXXXX'
lstFrom = elem1 // 10**(length-1)
lstTo = elem2 // 10**(length-1)
res = createAndSend(lstFrom, lstTo, mask, timeZone)
Проблемы начинаются когда встречаются резаные диапазоны, например начинаются с неровного числа или заканчиваются не кратно 10. Есть диапазоны, которые содержат 1 номер, 2 номера, 1234 номера и тп.
Есть вот такой диапазон для примера: 9410888290,9425504999,GMT+03:00
Основная цель - описать диапазон максимально коротким количеством строк по маске и конечно же не пропустить данные. С этим я зашел в тупик. Начал мудрить кучей проверок, даже показывать стыдно во что код начал превращаться:) Может изначально выбран неверный алгритм и можно все это упростить? В общем хотелось бы услышать дельных советов
Ответы (1 шт):
def ranges(low, high):
assert len(low) == len(high)
assert low <= high
n = len(low)
for i in range(n):
if low[i] != high[i]:
break
else:
i = n
if low[i:] == '0' * (n - i) and high[i:] == '9' * (n - i):
yield low[:i] + 'X' * (n - i)
return
assert low[i] < high[i]
for r in ranges(low[i:], low[i] + '9' * (n - i - 1)):
yield low[:i] + r
for d in range(int(low[i]) + 1, int(high[i])):
yield low[:i] + str(d) + 'X' * (n - i - 1)
for r in ranges(high[i] + '0' * (n - i - 1), high[i:]):
yield low[:i] + r
for r in ranges(*input().split()):
print(r)
$ echo 9410888290 9425504999 | python ranges.py 941088829X 94108883XX 94108884XX 94108885XX 94108886XX 94108887XX 94108888XX 94108889XX 9410889XXX 941089XXXX 94109XXXXX 9411XXXXXX 9412XXXXXX 9413XXXXXX 9414XXXXXX 9415XXXXXX 9416XXXXXX 9417XXXXXX 9418XXXXXX 9419XXXXXX 9420XXXXXX 9421XXXXXX 9422XXXXXX 9423XXXXXX 9424XXXXXX 94250XXXXX 94251XXXXX 94252XXXXX 94253XXXXX 94254XXXXX 9425500XXX 9425501XXX 9425502XXX 9425503XXX 9425504XXX