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?
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(','))
.
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')")
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:
- 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
)
- Then we append
M
to our result array, which array will stores allM
.
- 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;
}
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)))
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(", "))
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?
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(','))
.
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')")
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:
- 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 isM
) - Then we append
M
to our result array, which array will stores allM
. - 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;
}
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)))
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(", "))