въведете списък с 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))

Използвайки regex, това ще работи на произволно количество интервали:

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