Thursday, December 3, 2020

Get string in between braces when position of brace is given

 Let's say there is a string with braces and braces can be (),{},[] and the string has multiple sub-strings that are in braces. Given the position of start of a brace we need to print the string that qualifies. Say for example

Hello (This world is so beautiful (seriously) and I love it).

If the user inputs 1 as position, the output should be

This world is so beautiful (seriously) and I love it.

If the position is 2 then output should be seriously

Of course handle exceptions as well. How do we do that?


It looks tricky but a straight forward solution. The idea behind is to identify for a given brace where it ends. So, we leverage concept of stack. Algorithm is as follows

For each character in the string
If the character is opening brace, add it to a list
If the character is closing brace, pop the item from list (if there is no corresponding opening brace, we have an index out of range issue) and add the start and end positions to a dictionary/ hash map
After the complete string is traversed,
get the position from where the substring needs to be pulled. For that get the matching end and print the substring





def get_string_in_between(string_, brace, position):
    tmp_open_brace_pos = []
    brace_dict = {'(':')', '{':'}', '[':']'}
    start_end_pos_dict = {}
    if brace not in string_ or brace_dict.get(brace) not in string_:
        print('There are no recognized braces')
    else:
        for cnt, chr_ in enumerate(string_):
            if chr_ == brace:
                tmp_open_brace_pos.append(cnt)
            if chr_== brace_dict.get(brace):
                try:
                    start_end_pos_dict[tmp_open_brace_pos.pop()] = cnt
                except IndexError:
                    print('Unbalanced string. Too many closing braces')

    if tmp_open_brace_pos:
        print('There are too many opening braces')

    else:
        # sort the dictionary keys so we know the positions where the opening braces are
        ordered_indices = sorted(start_end_pos_dict)
        # indexes start at 0. However, the input will be >0 for position
        if position > len(ordered_indices):
            print('Out of range for start position. There are only {} braces'.format(str(len(ordered_indices))))
        else:
            return string_[ordered_indices[position-1]+1 : start_end_pos_dict[ordered_indices[position-1]]]


string = 'Hello (This world is so beautiful (seriously) and I love it)'


d = get_string_in_between(string, '(', 2)
print(d)

No comments: