Разбор кортежа из строки?
Скажем, что у меня есть строка, которая имеет ту же форму, что и кортеж, например, "(1,2,3,4,5)"
. Какой самый простой способ превратить это в настоящий кортеж? Пример того, что я хочу сделать, это:
tup_string = "(1,2,3,4,5)"
tup = make_tuple(tup_string)
Просто запустив tuple()
в строке, сделайте все это одним большим кортежем, в то время как то, что я хотел бы сделать, это понять строку как кортеж. Я знаю, что я могу использовать регулярное выражение для этого, но я надеялся, что там будет менее дорогостоящий путь. Идеи?
Ответы
Ответ 1
уже существует!
>>> 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(','))
.
Ответ 2
Вы можете анализировать свою строку без 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')")
Ответ 3
Мы также можем разобрать его сами.
Скажем, у нас есть кортеж, возвращаемый Python, как показано ниже:
((2, 'C/C++', 0, 'clang_cpp'), (3, 'Python相关', 0, 'python'))
Вот как мы это делаем
Сначала мы продолжаем читать символы в строке кортежа, но сохраняем последнюю позицию с запятой слева и количество точек с запятой, которые мы встречаем (мы можем называть ее левой точкой с запятой, как и для правой точки с запятой), всякий раз, когда мы встречаем правильную точку с запятой, мы делаем следующее:
- Возьмем подстроку из последней точки с запятой в текущую правую точку с запятой. (В
этой подстроки больше нет точек с запятой, мы просто разделим ее на
array by ",". Пусть говорят, что новый массив
M
)
- Затем мы добавляем
M
к нашему массиву результатов, который будет хранить все M
.
- В-третьих, удалите подстроку, взятую из исходной строки. Наконец, делайте то же самое, что и шаг 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;
}
Ответ 4
Я бы рекомендовал использовать 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)))