введите список 2D-координат в python от пользователя

Пользователь должен ввести набор координат, например (0,0), (0,1), (1,1), (1,0)

Код, который я написал для этого, выглядит так:

def get_coords():
    #user_input = raw_input("Enter a list of points. For example (0,0) (0,1) (1,1) (1,0)\n")
    print "Enter a list of points. For example (0,0) (0,1) (1,1) (1,0)\n"
    uin = sys.stdin.readline().strip() 
    try:
    #coords = map(int, uin.split(' '))
    coords = [tuple(map(int, point.replace('(', '').replace(')', '').split(','))) for point in uin.split(' ')]
    return coords
    except ValueError:
    print "Please enter the coordinates in the format mentioned"
    exit()

Я уверен, что есть более элегантный способ сделать это?


person meenakshi    schedule 11.06.2013    source источник


Ответы (3)


Замените пробелы на ',', а затем примените ast.literal_eval

>>> strs = '(0,0) (0,1) (1,1) (1,0)'
>>> from ast import literal_eval
>>> literal_eval(strs.replace(' ',','))
((0, 0), (0, 1), (1, 1), (1, 0))

Используя регулярное выражение, это будет работать с любым количеством пробелов:

>>> import re
>>> strs = '(0, 0)  (0, 1) ( 1, 1)    ( 1,  0)'
>>> literal_eval(re.sub('(\))(\s+)(\()','\g<1>,\g<3>',strs))
((0, 0), (0, 1), (1, 1), (1, 0))
person Ashwini Chaudhary    schedule 11.06.2013
comment
Отлично работает, спасибо! Хотя, если я добавлю запятые во входные данные, например (0,0), (0,1), (1,1), (1,0), и удалю часть replace () из кода, это не будет ' т работать. Это почему? - person meenakshi; 11.06.2013
comment
@meenakshi Должно работать нормально: literal_eval("(0,0), (0,1), (1,1), (1,0)") - person Ashwini Chaudhary; 11.06.2013
comment
Первый пример не работает для '(0,0), (0,1), (1,1), (1,0)'.replace(' ',','). Вы получите '(0,0),,(0,1),,(1,1),,(1,0)', как и следовало ожидать. Было бы лучше использовать split(), а затем проверять, заканчивается ли каждая подстрока на ')'; в противном случае используйте string.rstrip() с аргументом chars как ', '. Или что-то подобное. Разница между вашим ответом и комментарием заключается в отсутствии .replace() в вашем комментарии - конечно, без него все работает нормально! - person 2rs2ts; 11.06.2013
comment
@ 2rs2ts В примере, который я показал в своем ответе, нет запятых. - person Ashwini Chaudhary; 11.06.2013
comment
Вот что я говорю. Если вы не вводите запятые, вам нужно сделать .replace(' ',','), но если вы это сделаете, вам НЕ нужно этого делать. - person 2rs2ts; 11.06.2013

>>> from ast import literal_eval
>>> uin = raw_input("coords: ").split()
coords: (0,0) (0,1) (1,1) (1,0)
>>> uin
['(0,0)', '(0,1)', '(1,1)', '(1,0)']
>>> coords = [literal_eval(coord) for coord in uin]
>>> coords
[(0, 0), (0, 1), (1, 1), (1, 0)]

В своем файле вы можете просто написать это. Замените подсказку на то, что вам нравится.

from ast import literal_eval
try:
    coords = [literal_eval(coord) for coord in raw_input("coords: ").split()]
except ValueError:
    print "Please enter the coordinates in the format mentioned"
    exit()

literal_eval() вызывает исключение, если код небезопасен. См. документацию.

Обычный eval() - это плохо, потому что он может выполнять произвольный код, вводимый вашим пользователем!

person 2rs2ts    schedule 11.06.2013
comment
Ага, я избегаю eval () при вводе пользователем. Я не знал о literal_eval (), но теперь знаю. Спасибо! - person meenakshi; 11.06.2013

Просто добавьте запятые между кортежами, и вы можете безопасно преобразовать строку в кортеж кортежей:

import ast

def get_coords():
    print "Enter a list of points. For example (0,0), (0,1), (1,1), (1,0)"
    points = raw_input()

    while True:
        try:
            return ast.literal_eval(points)
        except SyntaxError:
            print "Please enter the coordinates in the format mentioned"

Вы получите результат примерно такой:

((0, 0), (0, 1), (1, 1), (1, 0))

И если вам абсолютно необходим список, просто пропустите его через list():

            return list(ast.literal_eval(points))
person Blender    schedule 11.06.2013