m = re.match(r'(\d+)(?:-(\d+))?$', string)
start = m.group(1)
end = m.group(2) or start
return list(range(int(start, 10), int(end, 10) + 1))
Прямо сейчас это способно обрабатывать строки в следующем формате и преобразовывать их в список...
"0-6" приводит к [0,1,2,3,4,5,6]
'7' приводит к [7]
В любом случае, я могу изменить обозначение, чтобы иметь возможность обрабатывать строки в следующем формате...
'1 2 3 4 5' приводит к [1,2,3,4,5]
Регулярные выражения не все, что нужно для жизни. В этом случае нет причин использовать регулярные выражения. Попробуйте это, это в два раза быстрее, чем, например, Shawn Chin to_num_list
на образцах данных '0-6 2 3-6'
(для всех данных, которые я пробовал на нем, он был примерно в 1,9 и 4,5 раза быстрее):
def included_numbers(s):
out = []
for chunk in s.split():
if '-' in chunk:
f, t = chunk.split('-')
out.extend(range(int(f), int(t)+1))
else:
out.append(int(chunk))
return out
try: ... except ValueError: ...
set()
вместо list
чтобы, если пользователь указывает перекрывающиеся диапазоны, результат не содержал дубликатов.
Я хотел бы придерживаться того же обозначения, а затем использовать re.findall()
для получения всех совпадений. пример
import re
def to_num_list(instr):
out = []
for m in re.finditer(r'(\d+)(?:-(\d+))?', instr):
if m.group(2) == None:
out.append(int(m.group(1)))
else:
start = int(m.group(1))
end = int(m.group(2))
out.extend(xrange(start, end + 1))
return out
Это даст вам возможность обрабатывать вменения, такие как "1 2 3 10-15"
. Пример использования:
>>> to_num_list("0-6")
[0, 1, 2, 3, 4, 5, 6]
>>> to_num_list("10")
[10]
>>> to_num_list("1 3 5")
[1, 3, 5]
>>> to_num_list("1 3 5 7-10 12-13")
[1, 3, 5, 7, 8, 9, 10, 12, 13]
и пропускает ошибочные входы (что может не обязательно быть тем, что вы хотите):
>>> to_num_list("hello world 1 2 3")
[1, 2, 3]
>>> to_num_list("")
[]
>>> to_num_list("1 hello 2 world 3")
[1, 2, 3]
>>> to_num_list("1hello2")
[1, 2]
m = re.match(r'(?:(\d+)(?:-(\d+))|(?:(\d+)(?:\s+|$))+)?$', string)
Затем просмотрите записи для группы 3.
Если вы согласны с использованием разделения, вы можете упростить свое регулярное выражение и позволить разделить дескриптор всех определений списка разделенных пробелами.
import re
def answer(string):
m = re.match(r'(\d+)-(\d+)$', string)
if m:
start = m.group(1)
end = m.group(2) or start
return list(range(int(start), int(end) + 1))
return map(int, string.split(' '))
Два входных формата могут быть сопоставлены не-жадным регулярным выражением (обозначаемым квантором? После *):
m = re.match(r'^(\d+)[0-9\-\s]*?(\d+)?$', string)
Всегда будет извлекать первое число и последнее число в m.group(1) и m.group(2) соответственно, или если есть только один номер, он будет сопоставлен в m.group(1)
См. Жадные и не жадные в документах python.
"1 3 5 2"
?