将字符串转换为元组

41
我需要编写一个函数,接收字符串'(1,2,3,4,5),(5,4,3,2,1)',并返回每个元组的第一个和最后一个元素组成的元组列表[(1,5),(5,1)]。
我的想法是:
def f(givenstring):
    a=givenstring.split(',')
    for i in a[0:-1]:
        tuple(int(i[0,-1]))

但是我现在卡住了...


1
像 re.findall() 或 eval() 这样思考(但请记住,eval 是邪恶的)。抱歉,没有时间给出完整答案。 - pyroscope
你能修复代码格式吗?(出于某种原因,我无法做到..) - Brigand
相关链接:link - Brigand
3个回答

83

您可以使用ast.literal_eval()

安全地评估表达式节点或包含Python表达式的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串,数字,元组,列表,字典,布尔值和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)]

1
注意,AST是Python2.6+的功能,我必须在我的Python2.5项目中使用eval。 - Kevin

33

你可以使用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)']

正则表达式模式指的是:

\( #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)]

这种方法根本不需要模块。但是它并不是非常健壮(如果输入字符串存在一些不一致性,例如括号和逗号之间有空格...), (... ,那么什么都不会起作用)。


1
是的,我知道。所以我想避免使用eval..而且我不太了解re.findall,如果可能的话,我也想避免使用它。 - Linus Svendsson
有没有一种方法可以将b、c和d列表推导合并为一个单独的列表推导? - Below the Radar
1
@BelowtheRadar 确定 [tuple(int(el2) for el2 in el.strip('()').split(',')) for el in a] - ovgolovin

7
在这种情况下,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)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接