brucezepplin
brucezepplin

Reputation: 9762

R: pass a vector of strings to replace all instances within a string

If I have:

mystring<-"I have one cat, two dogs and three rabbits"
numlist<-c("one","two","three")

How do I pass numlist into something like gsub and replace all instances of a match in mystring so that I get:

"I have ##NUMBER## cat, ##NUMBER## dogs and ##NUMBER## rabbits"

I have tried:

> lapply(mystring,arg1=numlist,function(x,arg1) gsub(arg1,"##NUMBER##",x))
[[1]]
[1] "I have ##NUMBER## cat, two dogs and three rabbits"

Warning message:
In gsub(arg1, "##NUMBER##", x) :
  argument 'pattern' has length > 1 and only the first element will be used

because gsub is not vectorized. However I thought lapply could take care of this?

Upvotes: 3

Views: 1874

Answers (3)

pe-perry
pe-perry

Reputation: 2621

Not an elegant way, but it works,

x <- "I have ##NUMBER## cat, ##NUMBER## dogs and ##NUMBER## rabbits"
numlist <- c("one","two","three")

for (i in 1:length(numlist)) {
  loc <- regexpr("##NUMBER##", x)
  start_loc <- loc[[1]]
  width <- attr(loc, "match.length")
  x <- paste(substr(x, 1, start_loc - 1), numlist[i], substr(x, start_loc + width, nchar(x)), sep = "")
}

Output:

> x
[1] "I have one cat, two dogs and three rabbits"

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545766

You can use lapply, or you can construct a regular expression from your search strings:

gsub(paste(numlist, collapse = '|'), '##NUMBER##', mystring)

This will match any of the strings in numlist.

When using lapply, you need to invert your arguments, since you want to apply the function over numlist, not over mystring; furthermore, your function must take exactly one argument:

lapply(numlist, function (num) gsub(num, '##NUMBER##', mystring))

This will, however, yield a different result; namely, it will return three result strings, each with a different word replaced:

[[1]]
[1] "I have ##NUMBER## cat, two dogs and three rabbits"

[[2]]
[1] "I have one cat, ##NUMBER## dogs and three rabbits"

[[3]]
[1] "I have one cat, two dogs and ##NUMBER## rabbits"

Upvotes: 2

akrun
akrun

Reputation: 887391

We can use gsubfn if we need to replace with numbers.

 library(gsubfn)
 gsubfn("\\w+", as.list(setNames(1:3, numlist)), mystring)
 #[1] "I have 1 cat, 2 dogs and 3 rabbits"

EDIT: I thought that we need to replace with numbers that corresponds to the words in 'numlist'. But, iff we need to replace with ##NUMBER## flag, one option is mgsub

 library(qdap)
 mgsub(numlist, "##NUMBER##", mystring)
 #[1] "I have ##NUMBER## cat, ##NUMBER## dogs and ##NUMBER## rabbits"

Upvotes: 4

Related Questions