2011-12-13 3 views
12

Мне нужно написать функцию, которая берет строку '(1,2,3,4,5), (5,4,3,2,1)' и возвращает список кортежей 1-й и последний элементы каждого кортежа, [(1,5), (5,1)]. Я думал:преобразование строки в кортеж

def f(givenstring): 
    a=givenstring.split(',') 
    for i in a[0:-1]: 
     tuple(int(i[0,-1])) 

, но здесь я stucked ..

+0

Думай больше как re.findall() или Eval() (но помните, Eval зло). Извините, нет времени для полного ответа. – pyroscope

+0

Можете ли вы исправить форматирование кода? (По какой-то причине я не могу ..) – FakeRainBrigand

+0

Связанный: [link] (http://stackoverflow.com/questions/1810109/parsing-a-string-which-represents-a-list-of-tuples) – FakeRainBrigand

ответ

14

Вы можете использовать eval. Я думаю, это будет самый короткий.

>>> s = '(1,2,3,4,5),(5,4,3,2,1)' 
>>> ts = eval(s) 
>>> ts 
((1, 2, 3, 4, 5), (5, 4, 3, 2, 1)) 
>>> tsp = [(el[0],el[-1]) for el in ts] 
>>> tsp 
[(1, 5), (5, 1)] 

Тем не менее, это не является хорошей практикой использовать eval.

Другой вариант - проанализировать строку, используя модуль re.

>>> a = re.findall('\([^)]*\)',s) 
>>> a 
['(1,2,3,4,5)', '(5,4,3,2,1)'] 

Regexp модели означает следующее:

\(#opening parenthesis 
[^)]* #from 0 to infinite symbols different from) 
\) #closing parenthesis 

.

>>> b = [el.strip('()') for el in a] 
>>> b 
['1,2,3,4,5', '5,4,3,2,1'] 
>>> c = [el.split(',') for el in b] 
>>> c 
[['1', '2', '3', '4', '5'], ['5', '4', '3', '2', '1']] 
>>> d = [tuple(int(el2) for el2 in el) for el in c] 
>>> d 
[(1, 2, 3, 4, 5), (5, 4, 3, 2, 1)] 

Кроме того, вы можете сделать следующее:

>>> [tuple(int(i) for i in el.strip('()').split(',')) for el in s.split('),(')] 
[(1, 2, 3, 4, 5), (5, 4, 3, 2, 1)] 

Этот подход не принимает модули на всех. Но он не очень надежный (если входная строка будет иметь некоторую несогласованность, например пробел между круглыми скобками и запятой ...), (..., тогда заметка будет работать).

+0

да, я знаю .. Поэтому я бы хотел избежать eval .. и я действительно не знаю re.findall, поэтому я хотел бы избежать этого тоже, если это возможно? –

+0

Есть ли способ объединить понимание списков b, c и d в единое понимание списка? –

+1

@BelowtheRadar Sure '[tuple (int (el2) для el2 в el.strip ('()'). Split (',')) для el в a]'. – ovgolovin

41

Вы можете использовать ast.literal_eval():

Безопасно оценить узел экспрессии или строку, содержащую выражение Python. Представленная строка или узел могут состоять только из следующих литеральных структур Python: строк, чисел, кортежей, списков, dicts, booleans и None.

Это может использоваться для безопасной оценки строк, содержащих выражения Python, из ненадежных источников без необходимости самостоятельно анализировать значения.

В вашем примере:

from ast import literal_eval 
s = '(1,2,3,4,5),(5,4,3,2,1)' 

l = literal_eval(s) 
print l 
# ((1, 2, 3, 4, 5), (5, 4, 3, 2, 1)) 

print [(x[0], x[-1]) for x in l] 
# [(1, 5), (5, 1)] 
+0

note, AST is python2.6 +, мне нужно использовать eval для моего проекта python2.5. – kevinf

0

В этом случае ast модуль может быть полезным:

>>> from ast import literal_eval 
>>> s = '(1,2,3,4,5),(5,4,3,2,1)' 
>>> my_tuples = literal_eval(s) 
>>> my_tuples 
((1, 2, 3, 4, 5), (5, 4, 3, 2, 1)) 

Итак, my_tuples есть кортеж кортежей вашей строки. Теперь мы можем получить первый и последний элемент всех кортежей, используя список понимание:

>> new_tuples = [(t[0], t[-1]) for t in my_tuples] 
>>> new_tuples 
[(1, 5), (5, 1)]