Как конвертировать различные форматы строки в список int? (Python)

1
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]

  • 0
    Вопрос мог бы сделать с лучшим названием. Если вы начнете с определенного мнения, что это должно быть сделано с помощью регулярных выражений, вы часто не получите правильный ответ. Назовите это тем, что вы хотите сделать, а не тем , что, как вы думаете, вы хотите сделать.
Теги:

5 ответов

6
Лучший ответ

Регулярные выражения не все, что нужно для жизни. В этом случае нет причин использовать регулярные выражения. Попробуйте это, это в два раза быстрее, чем, например, 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
  • 0
    +1 Я согласен, что регулярное выражение является излишним для этого вопроса. Чтобы справиться с нежелательными символами, можно легко обернуть соответствующий блок с помощью try: ... except ValueError: ...
  • 0
    Вы можете использовать set() вместо list чтобы, если пользователь указывает перекрывающиеся диапазоны, результат не содержал дубликатов.
Показать ещё 2 комментария
3

Я хотел бы придерживаться того же обозначения, а затем использовать 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]
1
m = re.match(r'(?:(\d+)(?:-(\d+))|(?:(\d+)(?:\s+|$))+)?$', string)

Затем просмотрите записи для группы 3.

  • 0
    Хотя это значительно увеличивает сложность, поэтому, возможно, вам следует делать это отдельно.
0

Если вы согласны с использованием разделения, вы можете упростить свое регулярное выражение и позволить разделить дескриптор всех определений списка разделенных пробелами.

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(' '))
0

Два входных формата могут быть сопоставлены не-жадным регулярным выражением (обозначаемым квантором? После *):

m = re.match(r'^(\d+)[0-9\-\s]*?(\d+)?$', string)

Всегда будет извлекать первое число и последнее число в m.group(1) и m.group(2) соответственно, или если есть только один номер, он будет сопоставлен в m.group(1)

См. Жадные и не жадные в документах python.

  • 0
    Что делать, если ввод "1 3 5 2" ?
  • 0
    ОП не спрашивал об этом формате ввода. Если цель вопроса заключалась в том, чтобы обработать какой-либо список чисел, то ваше общее решение работает здесь, где мое не удается. Однако, если цель состоит в том, чтобы выразить возрастающий список чисел, как в его двух примерах, мое регулярное выражение подходит для всех случаев и проще, чем ваше решение. Это компромисс.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню