我在寻找一种方法来扩展用斜杠分隔的数字。除了斜杠外,圆括号还可以在一些(或所有)数字周围使用,以表示一个“组”,该“组”可以重复(由括号后面的次数)或反向重复(后面跟着's‘,如第二组示例所示)。一些例子是:
1 -> ['1'] -> No slashes, no parentheses
1/2/3/4 -> ['1', '2', '3', '4'] -> basic example with slashes
1/(2)4/3 -> ['1', '2', '2', '2', '2', '3'] -> 2 gets repeated 4 times
1/(2/3)2/4 -> ['1', '2', '3', '2', '3', '4'] -> 2/3 is repeated 2 times
(1/2/3)2 -> ['1', '2', '3', '1', '2', '3'] -> Entire sequence is repeated twice
(1/2/3)s -> ['1', '2', '3', '3', '2', '1'] -> Entire sequence is repeated in reverse
1/(2/3)s/4 -> ['1', '2', '3', '3', '2', '4'] -> 2/3 is repeated in reverse在最一般的情况下,甚至可能有嵌套括号,我知道这通常使regex的使用变得不可能。在我需要处理的当前数据集中,没有这样的嵌套集,但我可以看到它在未来的潜在用途。例如:
1/(2/(3)2/4)s/5 -> 1/(2/3/3/4)s/5
-> 1/2/3/3/4/4/3/3/2/5
-> ['1', '2', '3', '3', '4', '4', '3', '3', '2', '5']当然,我知道regex不能做到所有这一切(特别是使用重复/反转的括号)。但是如果我能得到一个正则表达式,它至少可以将括号的字符串与非括号中的字符串分开,那么我可能会很容易地做一些循环来处理剩下的部分。所以,我要找的正则表达式是这样的:
1 -> ['1']
1/2/3/4 -> ['1', '2', '3', '4']
1/(2)4/3 -> ['1', '(2)4', '3']
1/(2/3)2/4 -> ['1', '(2/3)2', '4']
1/(2/(3)2/4)s/5 -> ['1', '(2/(3)/2/4)s', '5']然后,我可以循环这个结果,并继续展开任何括号,直到我只有数字。
编辑
在我最初的帖子里我还不太清楚。为了使示例尽可能简单,我可能过于简化了它们。这需要对数字>= 10和负数都有效。
例如:
1/(15/-23)s/4 -> ['1', '(15/-23)s', '4']
-> ['1', '15', '-23', '-23', '15', '4']发布于 2013-08-14 22:34:44
由于您正在处理嵌套括号,regex在这里对您帮助不大。它不能很容易地将字符串转换为列表,正如您在末尾所希望的那样。
您最好自己解析字符串。您可以尝试以下代码,以便在最后满足您的要求:
将字符串解析为list而不松开括号:
def parse(s):
li = []
open = 0
closed = False
start_index = -1
for index, c in enumerate(s):
if c == '(':
if open == 0:
start_index = index
open += 1
elif c == ')':
open -= 1
if open == 0:
closed = True
elif closed:
li.append(s[start_index: index + 1])
closed = False
elif open == 0 and c.isdigit():
li.append(c)
return li这将为字符串'1/(2/(3)2/4)s/5'提供以下列表:
['1', '(2/(3)2/4)s', '5']对于字符串'1/(15/-23)s/4',根据您更改的需求,这提供了:
['1', '(15/-23)s', '4']现在,您需要更好地处理括号的断裂,以获得不同的列表元素。
将带括号的字符串展开为单个list元素:
在这里,您可以使用正则表达式,只需一次处理最内部的括号:
import re
def expand(s):
''' Group 1 contains the string inside the parenthesis
Group 2 contains the digit or character `s` after the closing parenthesis
'''
match = re.search(r'\(([^()]*)\)(\d|s)', s)
if match:
group0 = match.group()
group1 = match.group(1)
group2 = match.group(2)
if group2.isdigit():
# A digit after the closing parenthesis. Repeat the string inside
s = s.replace(group0, ((group1 + '/') * int(group2))[:-1])
else:
s = s.replace(group0, '/'.join(group1.split('/') + group1.split('/')[::-1]))
if '(' in s:
return expand(s)
return s
li = parse('1/(15/-23)2/4')
for index, s in enumerate(li):
if '(' in s:
s = expand(s)
li[index] = s.split('/')
import itertools
print list(itertools.chain(*li))这将给出所需的结果:
['1', '15', '-23', '-23', '15', '4']上面的代码迭代从parse(s)方法生成的列表,然后对每个元素递归地展开最内部的括号。
发布于 2013-08-14 22:40:31
这是另一种方法来完成这个任务。
def expand(string):
level = 0
buffer = ""
container = []
for char in string:
if char == "/":
if level == 0:
container.append(buffer)
buffer = ""
else:
buffer += char
elif char == "(":
level += 1
buffer += char
elif char == ")":
level -= 1
buffer += char
else:
buffer += char
if buffer != "":
container.append(buffer)
return container发布于 2013-08-14 23:10:02
正则表达式是这个工作的完全错误的工具。对于为什么正则表达式是不合适的(如果你想知道为什么,这里有一门在线课程),有一个冗长而详尽的解释。一个简单的递归解析器很容易编写来处理这个问题,在调试正则表达式之前很可能就已经完成了。
这是一个缓慢的一天,所以我承担了自己写它自己,完成了博士考试。
def parse(s):
"""
>>> parse('1')
['1']
>>> parse('1/2/3/4')
['1', '2', '3', '4']
>>> parse('1/(2)4/3')
['1', '2', '2', '2', '2', '3']
>>> parse('1/(2/3)2/4')
['1', '2', '3', '2', '3', '4']
>>> parse('(1/2/3)2')
['1', '2', '3', '1', '2', '3']
>>> parse('1/(2/3)s/4')
['1', '2', '3', '3', '2', '4']
>>> parse('(1/2/3)s')
['1', '2', '3', '3', '2', '1']
>>> parse('1/(2/(3)2/4)s/5')
['1', '2', '3', '3', '4', '4', '3', '3', '2', '5']
"""
return _parse(list(s))
def _parse(chars):
output = []
while len(chars):
c = chars.pop(0)
if c == '/':
continue
elif c == '(':
sub = _parse(chars)
nextC = chars.pop(0)
if nextC.isdigit():
n = int(nextC)
sub = n * sub
output.extend(sub)
elif nextC == 's':
output.extend(sub)
output.extend(reversed(sub))
elif c == ')':
return output
else:
output.extend(c)
return output
if __name__ == "__main__":
import doctest
doctest.testmod()https://stackoverflow.com/questions/18243119
复制相似问题