heds1
heds1

Reputation: 3438

Repeating and incrementing a readline() user input x number of times

This function should take the integer that the user inputs in the first readline() prompt, and then run the next section of readline() inputs based on that integer.

If numSampFolders == 1, then it only requires one sample folder name, as per the code below. Similarly, if numSampFolders == 2, then it requires two sample folder names.

There must be a better way to write this than how I've set it up, though (and I don't really want to end up with dozens of if() statements just to cover every eventuality...). For example, if numSampFolders = 24, the code should ask the user, via readline(), to input 24 names and store those names as global variables. (I understand that this could be more easily done with list.files(), however there are folders in the same directory that are not required.) Thanks for ideas.

set_params <- function(){
    numSampFolders <- (readline("How many sample folders are you using? "))
    numSampFolders <<- as.numeric(numSampFolders)
    if (numSampFolders == 1)
        SampFolder1 <<- readline("Enter the name of your only sample folder: ")
    if (numSampFolders == 2)
        SampFolder1 <<- readline("Enter the name of sample folder 1: ")
        SampFolder2 <<- readline("Enter the name of sample folder 2: ")
}
if(interactive()) set_params()

Upvotes: 2

Views: 225

Answers (1)

CPak
CPak

Reputation: 13581

The general approach is to use lapply (or sapply/for) for iteration and the R verb assign. assign behaves like <-, and the trick to making assign behave like <<- is to specify the environment with envir = .GlobalEnv. See the following solution

set_params <- function(){
    numSampFolders <- (readline("How many sample folders are you using? "))
    numSampFolders <<- as.numeric(numSampFolders)
    if (numSampFolders == 1) {
        SampFolder1 <<- readline("Enter the name of your only sample folder: ")
    } else if (numSampFolders > 1) {
        lapply(seq_len(numSampFolders), function(i) assign(paste0("SampFolder", i), readline(paste0("Enter the name of sample folder ", i, ": ")), envir = .GlobalEnv))
    }
}
if(interactive()) set_params()

Here's the output of my console

ls()
# character(0)

# How many sample folders are you using? 2
# Enter the name of sample folder 1: ok
# Enter the name of sample folder 2: whatever
# [[1]]
# [1] "ok"

# [[2]]
# [1] "whatever"

ls()
# [1] "numSampFolders" "SampFolder1"    "SampFolder2"    "set_params"

SampFolder1  
# [1] "ok"

You may not like that lapply prints the values to the console (in this case, it's a side-effect). The following is what I'm referring to

# [[1]]
# [1] "ok"

In that case, you can use purrr::walk to loop without the side-effects.

library(purrr)
set_params <- function(){
    numSampFolders <- (readline("How many sample folders are you using? "))
    numSampFolders <<- as.numeric(numSampFolders)
    if (numSampFolders == 1) {
        SampFolder1 <<- readline("Enter the name of your only sample folder: ")
    } else if (numSampFolders > 1) {
        walk(seq_len(numSampFolders), function(i) assign(paste0("SampFolder", i), readline(paste0("Enter the name of sample folder ", i, ": ")), envir = .GlobalEnv))
    }
}

if(interactive()) set_params()

Upvotes: 1

Related Questions