I want a Python function that takes a string, and returns an array, where each item in the array is either a character, or another array of this kind. Nested arrays are marked in the input string by starting with '(' and ending with ')'.
Thus, the function would act like this:
1) foo("abc") == ["a", "b", "c"]
2) foo("a(b)c") == ["a", ["b"], "c"]
3) foo("a(b(c))") == ["a", ["b", ["c"]]]
4) foo("a(b(c)") == error: closing bracket is missing
5) foo("a(b))c") == error: opening bracket is missing
6) foo("a)b(c") == error: opening bracket is missing
Note: I'd prefer a solution that's purely functional.
Iterative.
def foo(xs):
stack = [[]]
for x in xs:
if x == '(':
stack[-1].append([])
stack.append(stack[-1][-1])
elif x == ')':
stack.pop()
if not stack:
return 'error: opening bracket is missing'
#raise ValueError('error: opening bracket is missing')
else:
stack[-1].append(x)
if len(stack) > 1:
return 'error: closing bracket is missing'
#raise ValueError('error: closing bracket is missing')
return stack.pop()
assert foo("abc") == ["a", "b", "c"]
assert foo("a(b)c") == ["a", ["b"], "c"]
assert foo("a(b(c))") == ["a", ["b", ["c"]]]
assert foo("a((b(c))d)(e)") == ['a', [['b', ['c']], 'd'], ['e']]
assert foo("a(b(c)") == "error: closing bracket is missing"
assert foo("a(b))c") == "error: opening bracket is missing"
assert foo("a)b(c") == 'error: opening bracket is missing'
def foo(s):
def foo_helper(level=0):
try:
token = next(tokens)
except StopIteration:
if level != 0:
raise Exception('missing closing paren')
else:
return []
if token == ')':
if level == 0:
raise Exception('missing opening paren')
else:
return []
elif token == '(':
return [foo_helper(level+1)] + foo_helper(level)
else:
return [token] + foo_helper(level)
tokens = iter(s)
return foo_helper()
And,
>>> foo('a((b(c))d)(e)')
['a', [['b', ['c']], 'd'], ['e']]
I would suggest two ways:
Either program your own recusive descent parser like here, or use pyparsing, something like
import pyparsing as pp
expr = pp.Forward()
expr << pp.Word(pp.alphas) + pp.Optional('(' + expr + ')') + pp.Optional(pp.Word(pp.alphas))
here you describe a recursive expression as a sequence of alphas, which can be interleaved by balanced parentheses. When you check this example for the outputs you will see how to get the desired output structure (though it will require some tweaking on your side and require some learning about pyparsing).
regards markus
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With