GPVS
GPVS

Reputation: 45

How to remove/replace specific parentheses from a string containing multiple parentheses in R

Given the following string of parentheses, I am trying to remove one specific parentheses, where the position of one of its bracket is marked with 1.

((((((((((((((((((********))))))))))))))))))
00000000000000000000000000000000010000000000

So for the above example, the solution I am looking for is

((((((((((-(((((((********)))))))-))))))))))
00000000000000000000000000000000010000000000

I am tried using strsplit function from stringr to split and get the indexes of the bracket marked with 1. But I am not sure how I can get the index of its corresponding closing bracket. Could anyone give some input on this..

What I did..

a = "((((((((((-(((((((********)))))))-))))))))))"
b = "00000000000000000000000000000000010000000000"
which(unlist(strsplit(b,"")) == 1)
#[1] 34
a_mod = unlist(strsplit(a,""))[-34]

here, I removed one bracket of the parentheses which I wanted to remove but I do not know how I can remove its corresponding opening bracket which is in 11th position in this example

Upvotes: 1

Views: 87

Answers (4)

G. Grothendieck
G. Grothendieck

Reputation: 269461

Locate the 1 in b giving pos2 and also calculate the length of b giving n. Then replace positions pos2 and pos1 = n-pos2+1 with minus characters. See ?gregexpr and ?nchar and ?substr for more info. No packages are used.

pos2 <- regexpr(1, b)
n <- nchar(a)
pos1 <- n - pos2 + 1
substr(a, pos1, pos1) <- substr(a, pos2, pos2) <- "-"

a
## [1] "((((((((((-(((((((********)))))))-))))))))))"

Upvotes: 2

Onyambu
Onyambu

Reputation: 79198

You could write a function that does the replacement the way you want:

strreplace <- function(x,y,val = "-")
{
  regmatches(x,regexpr(1,y)) <- val
  sub(".([(](?:[^()]|(?1))*+[)])(?=-)", paste0(val, "\\1"), x, perl = TRUE)
}

a <- "((((((((((((((((((********))))))))))))))))))"
b < -"00000000000000000000000000000000010000000000"
strreplace(a, b)
[1] "((((((((((-(((((((********)))))))-))))))))))"

# Nested paranthesis
a = "((((****))))((((((((((((((((((********))))))))))))))))))"
b = "00000000000000000000000000000000000000000000010000000000"
strreplace(a,b)
[1] "((((****))))((((((((((-(((((((********)))))))-))))))))))"

Upvotes: 0

user12728748
user12728748

Reputation: 8506

You should show what you have tried. One very simple way that would work for your example would be to do something like:

gsub("\\*){8}", "\\*)))))))-", "((((((((((((((((((********))))))))))))))))))")
#> [1] "((((((((((((((((((********)))))))-))))))))))"

Edit: In response to your question: It depends what you mean by other similar examples. If you go purely by position in the string, you already have an excellent answer from G. Grothendieck. If you want a solution where you want to replace the nth closing bracket, for example, you could do:

s <- "((((((((((((((((((********))))))))))))))))))"
replace_par <- function(n, string) {
    sub(paste0("(!?\\))(\\)){", n, "}"), 
     paste0(paste(rep(")", (n-1)), collapse=""), "-"), 
     string, perl = TRUE)}
replace_par(8, s)
#> [1] "((((((((((((((((((********)))))))-)))))))))"

Created on 2020-05-21 by the reprex package (v0.3.0)

Upvotes: 0

Greg
Greg

Reputation: 3650

Since the parentheses are paired the index of the close parentheses is just the length of the string minus the index of the open parentheses (they're equidistant from the string ends)

library(stringr)
string <- "((((((((((((((((((********))))))))))))))))))"
b <- "00000000000000000000000000000000010000000000"
location <- str_locate(b, "1")[1]
len <- str_length(string)

substr(string, location, location) <- "-"
substr(string, len-location, len-location) <- "-"
string
"(((((((((-((((((((********)))))))-))))))))))"

Upvotes: 0

Related Questions