How to Add Parenthesis Around a Substring in a String

How to add parenthesis around a substring in a string?

If your string always is a list of terms separated by ORs, you can just split and join:

>>> " OR ".join("({})".format(s.strip()) for s in message.split("OR"))
'(a and b amount) OR (c and d amount) OR (x and y amount)'

Adding parentheses around a string matched by a regex in Python

Solution 1:

>>> re.sub(r"\d{4}-\d{4}", r"(\g<0>)", "Alan Turing 1912-1954")
'Alan Turing (1912-1954)'

\g<0> is a backreference to the entire match (\0 doesn't work; it would be interpreted as \x00).

Solution 2:

>>> regex = re.compile(r"\d{4}-\d{4}")
>>> regex.sub(lambda m: '({0})'.format(m.group(0)), "Alan Turing 1912-1954")
'Alan Turing (1912-1954)'

Add parentheses to string condition

Using Dijkstra's shunting yard algorithm, you can use the following functions, inspired by pseudocode here, to wrap your expressions with parentheses in order of precedence.

Note that my earlier comment regarding building a tree was actually an unnecessary step, as you can instead work directly with the built postfix expression (although, postfix is simply a postorder traversal of the tree that would be generated, but the tree is not necessary here):

const precedence = ['|', '&']; // AND has a higher precedence than OR
const buildPostfix = expression => { const opStack = []; const postfix = []; const replaced = expression.replace(/AND/g, '&').replace(/OR/g, '|'); // replace the words with single characters to make parsing simpler for (let c of replaced) { // iterate through characters if (c === ' ') continue; // disregard a space if (c === '(') { opStack.push(c); } else if (c == ')') { let op = opStack.pop(); while (op !== '(') { // push all tokens in between a set of parentheses postfix.push(op); op = opStack.pop(); } } else if (precedence.includes(c)) { // check if character is operator or number while (opStack.length && precedence.indexOf(opStack[opStack.length - 1]) >= precedence.indexOf(c)) { // push operators with a higher precedence first postfix.push(opStack.pop()); } opStack.push(c); // push the current operator } else { postfix.push(c); // push the number onto the stack } }
while (opStack.length) { // push remaining operators postfix.push(opStack.pop()); }
return postfix;};
const addParentheses = expression => { const expStack = []; const postfix = buildPostfix(expression);
postfix.forEach(c => { if (precedence.includes(c)) { // check if character is operator or number const right = expStack.pop(); // get right operand const left = expStack.pop(); // get left operand expStack.push(`(${left} ${c} ${right})`); // create expression in form of (<left> <op> <right>) } else { expStack.push(c); // push number on stack } }); return expStack[0].replace(/&/g, 'AND').replace(/\|/g, 'OR'); // get the entire expression and re-substitute AND and OR for & and |, respectively};
const expressions = [ '1 AND 2 AND 3 OR (5 AND 6)', '1 AND 2', '1 AND 2 AND 3', '1 AND 2 OR 3', '1 AND (2 OR 3)', '1 AND (2 OR 3) AND 4', '1 AND (2 OR 4)', '(1 AND 2) OR (2 OR 4)'];const parenthesized = expressions.map(addParentheses);parenthesized.forEach((p, i) => console.log(`${expressions[i]} --> ${p}`));

Add missing parenthesis to a given string

The problem with your code is that you need to keep track of the numbers of non-terminated left parentheses as you step through the characters of the string, left-to-right, a number that can increase or decrease. You could obtain the desired strings as follows.

def add_closing_parens(str)
n = 0
s = str.each_char.with_object('') do |c,s|
s << c
case c
when '('
n += 1
when ')'
n -= 1
when '?', '.', '!'
if n > 0
s << ')'
n -= 1
end
end
end
n.zero? ? s : nil
end

n is the number of left parens that have not yet been closed. I added the exclamation mark as it can terminate a sentence.

add_closing_parens "Hey how are you? (Is (your) name Larry?"
#=> "Hey how are you?) (Is (your) name Larry?)"
add_closing_parens "(((Hey) how are you? how is it going."
#=> "(((Hey) how are you?) how is it going.)"
add_closing_parens "((Hey (how (are) you? What's happenin? Wow!"
#=> "((Hey (how (are) you?) What's happenin?) Wow!)"
add_closing_parens "Hey how (are) you? (What's (happenin? Wow!"
#=> "Hey how (are) you? (What's (happenin?) Wow!)"

str = "(((Hey (how (are) you? What's happenin? Wow!"
add_closing_parens str
#=> nil

If you want to be able to add missing right parentheses at the end, replace the last two lines with:

end << ')' * n

after which:

add_closing_parens str
#=> "(((Hey (how (are) you?) What's happenin?) Wow!))"

Ruby function for putting string in parentheses

I would use string interpolation:

str = " ( #{str} ) "

Some other options might be:

str = ' ( ' +  str + ' ) '
str = [' ( ', str, ' ) '].join

How to add closing parentheses when there are additional parentheses inside

You cannot match recursive patterns with built-in Python re, so you will have to pip install regex to install the PyPi regex module and use

return regex.sub(r'\btrim(\((?:[^()]++|(?1))*\))', r'ltrim(r\g<0>)', text) )

See the regex demo.

Details:

  • \btrim - matches a whole word trim
  • (\((?:[^()]++|(?1))*\)) - Group 1:
    • \( - a ( char
    • (?:[^()]++|(?1))* - zero or more chars other than ( and ) or the whole Group 1 pattern (recursed)
    • \) - a ) char.

The replacement is ltrim(r\g<0>): ltrim(r + the whole match + ).

See the Python demo:

import regex
text = "trim(str(p_name))"
print( regex.sub(r'\btrim(\((?:[^()]++|(?1))*\))', r'ltrim(r\g<0>)', text) )
## => ltrim(rtrim(str(p_name)))


Related Topics



Leave a reply



Submit