从字符串中解析元组?

时间:2012-03-18 23:03:54

标签: python python-2.7

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

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

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

4 个答案:

答案 0 :(得分:101)

already exists

>>> 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(','))

答案 1 :(得分:1)

您可以在不使用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')")

答案 2 :(得分:1)

我建议您使用literal_eval

如果您对literal_eval不满意或希望对转换的内容有更多控制权,您还可以反汇编字符串,转换值并重新创建元组。

听起来比实际上复杂,真的,它是一个单行:

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

如果元组中的任何元素(字符串)无法转换为ValueError,则会抛出int,例如字符串中的'1.2''(1.2, 3, 4)'

使用regex

可以实现同样的目标
import re
eg = '(102,117,108)'
et_tuple = tuple(map(int, re.findall(r'[0-9]+', eg)))

答案 3 :(得分:0)

我们也可以自己解析它。 假设我们有Python返回的元组,如下所示:

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

以下是我们的工作方式

首先,我们继续阅读元组字符串中的字符,但是只要我们遇到一个正确的分号,就会存储最后一个左分号的位置和我们遇到的分号数(我们可以称之为左分号,对于右分号也是如此) ,我们做以下事情:

  1. 从最后一个分号到当前右分号取一个子串 这个子串,没有更多的分号,我们只是把它分成了 数组“,”。假设新数组是M
  2. 然后我们将M追加到我们的结果数组中,该数组将存储所有M
  3. 第三,删除我们从原始字符串中获取的子字符串。     最后,做同样的事情,如第1步,直到左右     分号的级别为0。
  4. 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;
    }