从字符串中解析元组?

假设我有一个与元组形式相同的字符串,例如 "(1,2,3,4,5)"。把它转换成真正的元组最简单的方法是什么?我想做的一个例子是:

tup_string = "(1,2,3,4,5)"
tup = make_tuple(tup_string)

只要在字符串上运行 tuple(),整个事情就会变成一个大的元组,而我想要做的是将字符串理解为一个元组。我知道我可以使用正则表达式,但我希望有一个代价较低的方法。有什么想法吗?

65271 次浏览

已经存在了

>>> from ast import literal_eval as make_tuple
>>> make_tuple("(1,2,3,4,5)")
(1, 2, 3, 4, 5)

不过,要注意最后一个问题:

>>> make_tuple("(1)")
1
>>> make_tuple("(1,)")
(1,)

如果您的输入格式与这里的 Python 不同,则需要单独处理该情况,或者使用另一种方法,如 tuple(int(x) for x in tup_string[1:-1].split(','))

您可以在不使用 SyntaxError的情况下解析字符串

def parse_tuple(string):
try:
s = eval(string)
if type(s) == tuple:
return s
return
except:
return

如果解析成功,这个函数返回 Tuple,否则返回 None

print parse_tuple("('A', 'B', 'C')")

我们也可以自己解析它。 假设 Python 返回了 tuple,如下所示:

((2, 'C/C++', 0, 'clang_cpp'), (3, 'Python相关', 0, 'python'))

我们是这么做的

首先,我们继续读取元组字符串中的字符,但是存储最后一个左分号的位置和我们遇到的分号数(我们可以称之为左分号级别,右分号也是如此) ,每当我们遇到一个右分号时,我们会做以下事情:

  1. 从最后一个分号到当前右分号取一个子字符串 这个子字符串,没有分号,我们只是把它分成 假设新的数组是 M)
  2. 然后将 M附加到结果数组,该数组将存储 allM
  3. 第三,删除从原字符串中提取的子字符串。 最后,做相同的事情,如步骤1,直到右边和左边 分号的等级为0。

JavaScript 代码如下:

function parseTuple(t){
var lc = "(";
var rc = ")";
var lc_level = 0;
var rc_level = 0;
var last_lc = 0;
var last_rc = 0;
var result = [];
for(i=0;i<t.length;i++){
if(t[i] == lc){
lc_level++;
last_lc = i;
}else if(t[i] == rc){
rc_level++;
last_rc = i;
}
if(rc_level == 1){
var substr = t.slice(last_lc+1,last_rc);
var data = substr.split(",");
result.push(data);
lc_level--;
rc_level--;
i = 0;
t = t.slice(0,last_lc) + t.substring(last_rc+1);
}
if(lc_level == rc_level && lc_level==0){
break;
}
}
return result;
}

我建议使用 literal_eval

如果您不适合使用 literal_eval或者想要使用 对转换的内容有更多的控制权,您也可以反汇编字符串,转换值并重新创建元组。

听起来比实际情况要复杂得多,真的,这只是一句俏皮话:

eg = '(102,117,108)'
eg_tuple = map(int, eg.replace('(','').replace(')','').split(',')))

如果元组中的任何元素(字符串)不能转换为 int,这将抛出 ValueError,例如字符串中的 '1.2': '(1.2, 3, 4)'


正则表达式也可以做到这一点:

import re
eg = '(102,117,108)'
et_tuple = tuple(map(int, re.findall(r'[0-9]+', eg)))