将一串元组拆分为元组

时间:2018-09-05 21:24:22

标签: python

我有一串元组,其中每个元组都用逗号分隔。如何将其拆分为元组列表?

例如,我想分割此字符串:

"(2,3) (3, 4) ( 5, 4)"

进入此元组数组:

[(2,3) , (3,4),(5,4)]

请注意,元组中可能有空格(例如"(3, 4)"),因此str.split()然后使用eval()无效。

5 个答案:

答案 0 :(得分:3)

您可以将re.splitast.literal_eval一起使用:

import re, ast
result = [ast.literal_eval(i) for i in re.split('(?<=\))\s(?=\()', "(2,3) (3, 4) ( 5, 4)")]

输出:

[(2, 3), (3, 4), (5, 4)]

请注意,ast.literal_eval比内置eval更安全,因为ast.literal_eval不会盲目评估传递给它的内容,而是检查输入是否为有效的Python数据类型

但是,如果字符串形式的元组没有用空格隔开,即"(2,3)(3, 4)(5, 6)",则上述方法将无效。在这种情况下,您可以创建一个小型解析器:

class Parse:
  def __init__(self, _input, _start=''):
    self.data, self.group, self.content = _input, _start, []
    self.parse()
  def __iter__(self):
    yield from map(ast.literal_eval, self.content)
  def parse(self):
    _val = next(self.data, None)
    if _val is not None:
       if _val == '(':
         r = Parse(self.data, _start="(")
         self.content.extend(r.content)
         self.data = r.data
       elif _val == ')':
         self.content.append(self.group+')')
       else:
         self.group += _val
       self.parse()

final_result = list(Parse(iter("(2,3)(3, 4)(5, 6)")))

输出:

[(2, 3), (3, 4), (5, 6)]

答案 1 :(得分:1)

如果这些数字始终像您声明的那样是两位数的元组,则只需使用re.findall

>>> out = re.findall(r'(\d+),\s*(\d+)', s)
>>> out
[('2', '3'), ('3', '4'), ('5', '4')]

如果需要这些作为整数:

>>> [tuple(map(int, i)) for i in out]
[(2, 3), (3, 4), (5, 4)]

答案 2 :(得分:1)

另一种方式可能是:

  • 首先,您可以按逗号分割并获取所有数字的列表。
  • 然后,使用zip,以便使用::21::2通过从起始位置开始的第二个位置跳过其他数字来分隔数字列表。

my_str = "(2,3) (3, 4) ( 5, 4)"
# getting list of digits only
all_numbers = [int(ch) for i in my_str.split(',') for ch in i if ch.isdigit()]
# using zip to convert into tuples
result = list(zip(all_numbers[::2], all_numbers[1::2]))
print(result)

输出为:

[(2, 3), (3, 4), (5, 4)]

答案 3 :(得分:0)

您可以使用re.sub,替换元组之间的空格,然后在literal_eval中添加括号和提要以解释为Python数据结构:

>>> s="(2,3) (3, 4) ( 5, 4)"
>>> from ast import literal_eval
>>> import re
>>> literal_eval("["+re.sub(r'(?<=\))[ \t]*(?=\()',',',s)+"]")
[(2, 3), (3, 4), (5, 4)]

甚至在元组之间没有空格的情况下也可以使用:

>>> s="(2,3)(3, 4)( 5, 4)"
>>> literal_eval("["+re.sub(r'(?<=\))[ \t]*(?=\()',',',s)+"]")
[(2, 3), (3, 4), (5, 4)]

答案 4 :(得分:0)

如果您不想使用任何库或评估程序,则可以尝试使用列表理解:

public class RetryTest {


    @Test
    public void execute() throws AggregateException {

        Integer result = Retry.execute(getCallableCalculater(), Duration.ofSeconds(1), 3);
        assertEquals(9, java.util.Optional.ofNullable(result));
    }

    private Callable<Integer> getCallableCalculater() {

        final Integer[] counter = {0};
        return () -> {
            for (int i = 0; i < 3; ++i) {
                counter[0]++;
                System.out.println(MessageFormat.format(
                        "Counter = {0}", Integer.toString(counter[0])));
            }
            if (counter[0] < 6)
                throw new Exception();
            return counter[0];
        };
    }
}

输出:

a="(2,3) (3, 4) ( 5, 4)"
[tuple(map(int,e.split(','))) for e in a.replace(' ','')[1:-1].split(')(')]

通过删除所有空格并取出第一个和最后一个括号,除以[(2, 3), (3, 4), (5, 4)] ,然后将剩余的字符串转换为带有int的元组,可以实现此目的