The following function removes text inside parenthesis, also checks for balanced brackets. Example:
RemoveTextInsideParenthesis('Yahoo (Inc)')
will return 'Yahoo'
Any suggestions in how to improve readability/simplify it?
def RemoveTextInsideParenthesis(text: str) -> str:
"""Remove text inside brackets or nested brackets.
Creates an array: ['(',')'...], then for each character in text string
we compare if character is a bracket, if it is we update a status array.
Based on status array we can evaluate if brackets are open and close correctly
and then capture text outside parenthesis.
Using divmod function we extract index of brackets array.
Take two (non complex) numbers as arguments and return a pair of numbers
consisting of their quotient and remainder.
Documentation for brackets:
https://www.unicode.org/charts/nameslist/n_2000.html
Args:
text: Text to be clean up.
Returns:
Text inside parenthesis
"""
openers = (u'(<[{\u0f3a\u0f3c\u169b\u2045\u207d\u208d\u2329\u2768'
u'\u276a\u276c\u276e\u2770\u2772\u2774\u27c5\u27e6\u27e8\u27ea'
u'\u27ec\u27ee\u2983\u2985\u2987\u2989\u298b\u298d\u298f\u2991'
u'\u2993\u2995\u2997\u29d8\u29da\u29fc\u2e22\u2e24\u2e26\u2e28'
u'\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d'
u'\u301d\ufd3e\ufe17\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41'
u'\ufe43\ufe47\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff5f\uff62'
u'\xab\u2018\u201c\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c\u2e20'
u'\u201a\u201e\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d'
u'\u2e1d\u2e21\u201b\u201f')
closers = (u')>]}\u0f3b\u0f3d\u169c\u2046\u207e\u208e\u232a\u2769'
u'\u276b\u276d\u276f\u2771\u2773\u2775\u27c6\u27e7\u27e9\u27eb'
u'\u27ed\u27ef\u2984\u2986\u2988\u298a\u298c\u298e\u2990\u2992'
u'\u2994\u2996\u2998\u29d9\u29db\u29fd\u2e23\u2e25\u2e27\u2e29'
u'\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e'
u'\u301f\ufd3f\ufe18\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42'
u'\ufe44\ufe48\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff60\uff63'
u'\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d\u2e21'
u'\u201b\u201f\xab\u2018\u201c\u2039\u2e02\u2e04\u2e09\u2e0c'
u'\u2e1c\u2e20\u201a\u201e')
# Interleave openers and closers: ['(',')'...]
brackets = [value for pair in zip(openers, closers) for value in pair]
count = [0] * (len(brackets) // 2) # Count open/close brackets as array.
clean_string = []
for character in text:
for i, bracket in enumerate(brackets):
if character == bracket: # Found a bracket in text.
# Take index(i) of brackets and 2 as arguments, return a tuple
# consisting of their quotient and remainder (a, b).
# When index is even, reminder = 0 is an open bracket.
# ['(',')','[',']',...] = [0, 1, 2, 3,...]
bracket_kind, is_close = divmod(i, 2)
# Keep track of brackets in string via count array by adding 1 when an
# open bracket is seen or substracting 1 when is closed.
# (-1)**0 = 1, (-1)**1 = -1. Balanced brackets, sum will be 0.
count[bracket_kind] += (-1)**is_close
if count[bracket_kind] < 0: # Unbalanced bracket.
count[bracket_kind] = 0
break
else: # Character is not a bracket.
if not any(count): # Outside brackets.
clean_string.append(character)
# Return text outside brackets or text if after removing brackets is empty.
return ''.join(clean_string).strip() if clean_string else text.strip()
'This is [a test { and a simple] one}. Isn\'t it?'
is shortened to'This is . Isn\'t it?'
; this doesn't feel like any balancing is at play, only that the first opener is matched to the last closer… I would have expected something like'This is one}. Isn\'t it?'
instead or at least'This is [a test . Isn\'t it?'
. \$\endgroup\$