简体   繁体   中英

Modify the object without using return in R function

I am trying to reverse a string without using extra space in R. Below is the code for the same. My question is how to get the ReverseString function change the input without using extra space. I even tried using <<- without any luck.

ReverseString <- function(TestString){
  TestString <- unlist(strsplit(TestString, ""))
  Left <- 1
  Right <- length(TestString)
  while (Left < Right){
    Temp <- TestString[Left]
    TestString[Left] <- TestString[Right]
    TestString[Right] <- Temp
    Left <- Left + 1
    Right <- Right - 1
  }
  return(paste(TestString, collapse = ""))

}
## Input
a = "StackOverFlow"
## OutPut
ReverseString(a)
"wolFrevOkcatS"
## 
a
"StackOverFlow"

It is always better to take advantage of the vectorization in R (instead of for or while loops). So, in base-R, without any packages, it would be something like:

ReverseString <- function(x) {
  #splitstring splits every character, and rev reverses the order
  out <- rev(strsplit(x, split = '')[[1]])
  #paste to paste them together
  paste(out, collapse = '')
}

a <- "StackOverFlow"
ReverseString(a)
#[1] "wolFrevOkcatS"

It can be done easily with stringi

library(stringi)
a <- "StackOverFlow"
stri_reverse(a)
#[1] "wolFrevOkcatS"

According to your comment you want to reverse the string without calling any function that does the reversal, ie no rev and co. Both of the solutions below do this.

I think you are also trying to modify global a from within the function, which is why you tried <<- . I'm not sure why it didn't work for you, but you might have used it incorrectly.

You should know that using <<- alone does not mean that you are using less space. To really save space you would have to call or modify global a at each step in your function where you call or modify TestString . This would entail some combination of assign , do.call , eval and parse - not to mention all the paste ing you would have to do to access elements of a by integer position. Your function would end up bulky, nearly unreadable, and very likley less efficient due to the numerous function calls, despite having saved a negligible amount of space by not storing a copy of a . If you're dead set on creating such an abomination, then take a look at the functions I just listed and figure out how to use them.

Your energy would be better spent by improving upon you string-reversing function in other ways. For example, you can shorten it quite a bit by using a numerical sequence such as 13:1 in sapply :

reverse_string <- function(string) {
    vec <- str_split(string, "")[[1]]
    paste(sapply(length(vec):1, function(i) vec[i]), collapse = "")
}

reverse_string("StackOverFlow")

#### OUTPUT ####

[1] "wolFrevOkcatS"

If your interviewers also have a problem with reverse sequences then here's another option that's closer to your original code, just a little cleaner. I also did my best to eliminate other areas where "extra space" was being used (indices stored in single vector, no more Temp ):

reverse_string2 <- function(string){
    vec <- str_split(string, "")[[1]]
    i_vec <- c(1, length(vec))

    while(i_vec[1] < i_vec[2]) {
        vec[i_vec] <- vec[c(i_vec[2], i_vec[1])]
        i_vec <- i_vec + c(1, -1)
    }

    paste(vec, collapse = "")
}

reverse_string2("StackOverFlow")

#### OUTPUT ####

[1] "wolFrevOkcatS"

I'm not sure I understood exactly the problem, but I think you're looking for a way to reverse the string object and automatically assign it to the original object without having to do a <- ReverseString(a) (assuming this is the reason why you tried using <<- ). My solution to this is using deparse(substitute()) to read the original variable name inside the function and assign (using envir = .GlobalEnv ) to assign your result over the original variable.

ReverseString <- function(TestString){

  nm <- deparse(substitute(TestString))

  TestString <- unlist(strsplit(TestString, ""))
  Left <- 1
  Right <- length(TestString)
  while (Left < Right){
    Temp <- TestString[Left]
    TestString[Left] <- TestString[Right]
    TestString[Right] <- Temp
    Left <- Left + 1
    Right <- Right - 1
  }

  assign(nm, paste(TestString, collapse = ""), envir = .GlobalEnv)

}

## Input
a = "StackOverFlow"

ReverseString(a)

a
#[1] "wolFrevOkcatS"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM