Parse a tuple from a string?

Question:

Say I have a string that’s of the same form a tuple should be, for example, "(1,2,3,4,5)". What’s the easiest way to convert that into an actual tuple? An example of what I want to do is:

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

Just running tuple() on the string make the whole thing one big tuple, whereas what I’d like to do is comprehend the string as a tuple. I know I can use a regex for this, but I was hoping there’s a less costly way. Ideas?

Asked By: Eli

||

Answers:

It already exists!

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

Be aware of the corner-case, though:

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

If your input format works different than Python here, you need to handle that case separately or use another method like tuple(int(x) for x in tup_string[1:-1].split(',')).

Answered By: Niklas B.

You can parse your string without SyntaxError

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

This function return the Tuple if parse is success. Otherwise return None.

print parse_tuple("('A', 'B', 'C')")
Answered By: Shameem

We can also parse it by ourself.
Let’s say we have tuple returned by Python like below:

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

Here’re how we do it

First, we keep reading the characters in the tuple string but stores the last left semicolon’s position and how many semicolons we have meet (we can call it left semicolon level, as so for right semicolons), whenever we meet a right semicolon, we do things below:

  1. Take a substring from last semicolon to current right semicolon.(In
    this substring, there is no more semicolons, we just split it into
    array by “,”. Let’s say the new array is M)
  2. Then we append M to our result array, which array will stores allM.
  3. Thirdly, delete the substring we taken from the original string.
    Finally, do the same things like step 1 till the right and left
    semicolon’s level comes to 0.

JavaScript code is like below:

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

Answered By: hcnak

I would recommend using literal_eval.

If you are not comfortable with literal_eval or want to have more control on what gets converted you can also disassemble the string, convert the values and recreate the tuple.

Sounds more complicated than it is, really, it’s a one-liner:

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

This would throw a ValueError if any element (string) in the tuple is not convertible to int, like, for example the '1.2' in the string: '(1.2, 3, 4)'.


The same can be achieved with regex:

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

Simplest way to do this (without ast):

def _make_tuple(self, val: str) -> tuple:
    """
    Convert a string representation of a tuple to a tuple.

    Example:
        "('item1', 'item2')" -> ('item1', 'item2')
    """
    return tuple(v.lstrip("('").rstrip("')") for v in val.split(", "))
Answered By: trybek_4
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.