Does the ternary operator exist in R?

后端 未结 7 1207
日久生厌
日久生厌 2020-12-22 16:52

As the question asks, is there a control sequence in R similar to C\'s ternary operator? If so, how do you use it? Thanks!

7条回答
  •  时光说笑
    2020-12-22 17:21

    As if is function in R and returns the latest evaluation, if-else is equivalent to ?:.

    > a <- 1
    > x <- if(a==1) 1 else 2
    > x
    [1] 1
    > x <- if(a==2) 1 else 2
    > x
    [1] 2
    

    The power of R is vectorization. The vectorization of the ternary operator is ifelse:

    > a <- c(1, 2, 1)
    > x <- ifelse(a==1, 1, 2)
    > x
    [1] 1 2 1
    > x <- ifelse(a==2, 1, 2)
    > x
    [1] 2 1 2
    

    Just kidding, you can define c-style ?::

    `?` <- function(x, y)
        eval(
          sapply(
            strsplit(
              deparse(substitute(y)), 
              ":"
          ), 
          function(e) parse(text = e)
        )[[2 - as.logical(x)]])
    

    here, you don't need to take care about brackets:

    > 1 ? 2*3 : 4
    [1] 6
    > 0 ? 2*3 : 4
    [1] 4
    > TRUE ? x*2 : 0
    [1] 2
    > FALSE ? x*2 : 0
    [1] 0
    

    but you need brackets for assignment :(

    > y <- 1 ? 2*3 : 4
    [1] 6
    > y
    [1] 1
    > y <- (1 ? 2*3 : 4)
    > y
    [1] 6
    

    Finally, you can do very similar way with c:

    `?` <- function(x, y) {
      xs <- as.list(substitute(x))
      if (xs[[1]] == as.name("<-")) x <- eval(xs[[3]])
      r <- eval(sapply(strsplit(deparse(substitute(y)), ":"), function(e) parse(text = e))[[2 - as.logical(x)]])
      if (xs[[1]] == as.name("<-")) {
        xs[[3]] <- r
            eval.parent(as.call(xs))
      } else {
        r
      }
    }       
    

    You can get rid of brackets:

    > y <- 1 ? 2*3 : 4
    > y
    [1] 6
    > y <- 0 ? 2*3 : 4
    > y
    [1] 4
    > 1 ? 2*3 : 4
    [1] 6
    > 0 ? 2*3 : 4
    [1] 4
    

    These are not for daily use, but maybe good for learning some internals of R language.

提交回复
热议问题