问题
I am trying to create a function where users can select the operator they want to use, which result in a different output. But I can't seem to get it to work. I know that we can't assign operators into an R object and then use it as an operator based on the R object name. Is there a way I could do this? Or perhaps a better way to write the function?
test <- function(items, operator = "+"){
bank_alpha <- matrix(ncol=6)
colnames(bank_alpha) <- colnames(bank_alpha, do.NULL = FALSE, prefix = "Q")
colnames(bank_alpha)[6] <- "A"
alphabet <- LETTERS[seq(1:26)]
for (i in 1:items) {
item <- c(alphabet[i], alphabet[i operator 1], alphabet[i operator 2], alphabet[i operator 3], alphabet[i operator 4], alphabet[i operator 5])
bank_alpha <- rbind(bank_alpha, item)
bank_alpha <- na.omit(bank_alpha)
}
return(bank_alpha)
}
test(items=4, operator = "-")
回答1:
Check out do.call, which takes the name of a function as an argument. With
operator <- "+"
do.call(operator, list(2,3)
you will get 5 as the result.
In your example:
test <- function(items, operator = "+"){
bank_alpha <- matrix(ncol=6)
colnames(bank_alpha) <- colnames(bank_alpha, do.NULL = FALSE, prefix = "Q")
colnames(bank_alpha)[6] <- "A"
alphabet <- LETTERS[seq(1:26)]
for (i in 1:items) {
item <- c(alphabet[i], alphabet[do.call(operator, list(i,1))], alphabet[do.call(operator, list(i,2))], alphabet[do.call(operator, list(i,3))], alphabet[do.call(operator, list(i,4))], alphabet[do.call(operator, list(i,5))])
bank_alpha <- rbind(bank_alpha, item)
bank_alpha <- na.omit(bank_alpha)
}
return(bank_alpha)
}
test(items=4, operator = "*")
Beware, "-" doesn't make sense in this case.
回答2:
You can use the get() functionally to dynamically call the operator functions, e.g.:
> get('+')(5, 2)
[1] 7
The get() function takes a string as input and returns a reference to the function corresponding to that string, if it exists.
Usually operators are called with one function argument on the left and one on the right (e.g. 5 + 2).
The + operator function itself however just takes two arguments as input:
> args('+')
function (e1, e2)
NULL
This is why we can call it as we did above.
回答3:
You can define your own operators in R using the % sign, which would allow you to use the infix notation in your code. See a related question for more details.
test <- function(items, `%op%` = `+`){
bank_alpha <- matrix(ncol=6)
colnames(bank_alpha) <- colnames(bank_alpha, do.NULL = FALSE, prefix = "Q")
colnames(bank_alpha)[6] <- "A"
alphabet <- LETTERS[seq(1:26)]
for (i in 1:items) {
item <- c(alphabet[i], alphabet[i %op% 1], alphabet[i %op% 2], alphabet[i %op% 3], alphabet[i %op% 4], alphabet[i %op% 5])
bank_alpha <- rbind(bank_alpha, item)
bank_alpha <- na.omit(bank_alpha)
}
return(bank_alpha)
}
test(items=4, `%op%` = `*`)
来源:https://stackoverflow.com/questions/39316116/assigning-operators-into-an-r-variable