Проверка ввода пользователя с помощью регулярного выражения - PullRequest
0 голосов
/ 21 ноября 2018

У меня очень ограниченный опыт работы с регулярными выражениями, поэтому я надеюсь, что кто-нибудь может мне помочь.

Я делаю игру на Python 3 с прямоугольной сеткой в ​​качестве доски.Я пытаюсь сделать так, чтобы пользователи могли вводить несколько координат доски одновременно в следующей форме в строку с именем coords:

(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)

Я хочу, чтобы вывод представлял собой список кортежей с именем cells в аналогичной форме:

[(x1, y1), (x2, y2), (x3, y3), ... (xn, yn)]

По сути Я хочу имитировать, как кортежи могут быть написаны в коде Python.

Сейчас я использую:

cells = [tuple(coords[i.find('(') + 1: i.rfind(')')].split(',')) for i in coords.split()]

, который дает желаемый результат для входных данных в форме (1,2) (3,4) (5,6), без пробелов внутри введенных кортежей и пробелов между кортежами.Тем не менее, это ломается для входов, не следующих точно за этой формой, и ничего не делает для проверки правильности входных данных.Для каждого x- и y-значения в кортежах cells, мне нужно проверить , что:

  1. type (y-value) == type (x-value)) == int
  2. 0 <= значение y <game_board.height </li>
  3. 0 <= значение x <game_board.width </li>

В идеале, если пользователивводит несколько действительных координат и несколько недействительных, действительные кортежи будут добавлены к cells, и пользователю будет выдано сообщение, подобное "The following coordinates were invalid: (x1, y1), ...".

Я знаю, что мог бы сделать все это с путаницей циклови управление потоком, но есть ли еще Pythonic способ сделать это с помощью регулярного выражения ?

Редактировать: правописание

1 Ответ

0 голосов
/ 21 ноября 2018

Регулярное выражение используется для проверки общей структуры - остальное делается без регулярного выражения:

inp = "(3, 4), (a, 7), (-3, 3), (3, 3)"

def MaybeInt(n):
    """Returns an int if possible, else the original value."""
    try:
        return int(n)
    except:
        return n

def inX(n):
    """True if inside X of board."""
    return 0<=n<5

def inY(n):
    """True if inside Y of board."""
    return 0<=n<5

def structOk(t):
    import re
    return re.match(r'^\s*([^,]+,[^,]+\)\s*(?:,\s*\([^,]+,[^,]+\))*)\s*$',t)

def validate(t):
    t = t.replace(" ","")
    if not structOk(t):
        raise ValueError("Structually unsound - try again: "+t)

    k = [ x.lstrip("(") for x in t.replace(" ","").rstrip(")").split("),")]
    tups = [ tuple(map(MaybeInt,tu.split(","))) for tu in k]

    # our "decider" for whats valid/invalid which is used to divide the tuples
    # into our valid/invalid return list's
    test = lambda q: all(isinstance(num,int) for num in q) and inX(q[0]) and inY(q[1])


    rv = [[],[]]  # prepare and append by our decider test
    for k in tups:
        # True == 1, False == 0
        rv[1-test(k)].append(k)

    return rv

valid, invalid = validate(inp)

print(valid)
print(invalid)

Вывод:

[(3, 4), (3, 3)]    # valid
[('a', 7), (-3, 3)] # invalid

См. https://regex101.com/r/OrHGaR/1 для регулярного выражения и подробного объяснения.

Краткое описание: Он ищет (..., ...) с ... не будучи, - вы можете уточнить его, используя fe [1234567890a-zA-Z] вместо [^,] но потом он пойдет в ValueError раньше, чем позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...