Reputation: 300
I'm trying to get a list of tuples with the indices of all sets of parentheses in a string. I can find the left and right parens independently easily with list comprehensions:
s = "12(34)567"
left_parens = [i for i,j in enumerate(s) if j == "("]
right_parens = left_parens = [i for i,j in enumerate(s) if j == ")"]
The most logical way to turn these separate lists into a list of tuples with (left paren, right paren) pairs is with the zip function.
parens = zip(right_parens,left_parens)
print(list(parens))
From this I would expect to yield:
[(2,5)]
But instead, I get:
[(5,5)]
Even if I switch the order like this:
parens = zip(left_parens,right_parens)
The result is still [(5,5)].
What am I missing?
Upvotes: 3
Views: 935
Reputation: 77860
The problem is here:
right_parens = left_parens = [ ... ]
You set the two lists to the same memory area; they are now the same list. Keep them separate:
left_parens = [i for i,j in enumerate(s) if j == "("]
right_parens = [i for i,j in enumerate(s) if j == ")"]
EXTENSION
Note that your algorithm won't work for nested parentheses:
s = "1(2(34)56)7"
Output:
[(1, 6), (3, 9)]
You can solve this with a counter: pre-increment for each Lparen, post-decrement for each Rparen. Mark each paren location with its nesting level:
string 1(2(34)56)7(8)
marker -1-2--2--1-1-1
From here, move from the inside out: match the 2's, left to right (only one pair), then the 1's (two pairs). Coding is left as an exercise for the student. :-) From here, you can
Upvotes: 7