आर में टर्नेरी ऑपरेटर मौजूद है?


175

जैसा कि सवाल पूछता है, क्या सी के टर्नेरी ऑपरेटर के समान आर में एक नियंत्रण अनुक्रम है ? यदि हां, तो आप इसका उपयोग कैसे करते हैं? धन्यवाद!


1
क्या आप कुछ अधिक शक्तिशाली चाहते हैं ifelse, या सिर्फ एक अधिक कॉम्पैक्ट रूप?
कार्ल विटथॉफ्ट

@CarlWitthoft अधिकतर अधिक कॉम्पैक्ट रूप; बस लेखन को बचाने का एक तरीका है if (x>1) y=2 else y=3y=एक बार लिखना एक निश्चित अपील है।
पलक

जवाबों:


302

जैसा ifकि कार्य है Rऔर नवीनतम मूल्यांकन लौटाता है, अगर-और के बराबर है ?:

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

R की शक्ति वैश्वीकरण है। टर्नरी ऑपरेटर का वैश्वीकरण है 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

केवल मजाक कर रहे हैं, आप सी-शैली को परिभाषित कर सकते हैं ?::

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

यहाँ, आपको कोष्ठक के बारे में ध्यान रखने की आवश्यकता नहीं है:

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

लेकिन आपको असाइनमेंट के लिए कोष्ठक चाहिए :(

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

अंत में, आप सी के साथ बहुत समान तरीके से कर सकते हैं:

`?` <- 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
  }
}       

आप कोष्ठक से छुटकारा पा सकते हैं:

> 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

ये दैनिक उपयोग के लिए नहीं हैं, लेकिन आर भाषा के कुछ आंतरिक सीखने के लिए शायद अच्छा है।


23

जैसा कि बाकी सभी ने कहा, उपयोग करें ifelse, लेकिन आप ऑपरेटरों को परिभाषित कर सकते हैं ताकि आपके पास लगभग टर्नरी ऑपरेटर सिंटैक्स हो।

`%?%` <- function(x, y) list(x = x, y = y)
`%:%` <- function(xy, z) if(xy$x) xy$y else z

TRUE %?% rnorm(5) %:% month.abb
## [1]  0.05363141 -0.42434567 -0.20000319  1.31049766 -0.31761248
FALSE %?% rnorm(5) %:% month.abb
## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
# or, more generally
condition %?% value1 %:% value2

यह वास्तव में काम करता है यदि आप संचालकों को %संकेतों के बिना परिभाषित करते हैं , तो आपके पास हो सकता है

`?` <- function(x, y) if(x) y[[1]] else y[[2]]
`:` <- function(y, z) list(y, z)

TRUE ? rnorm(5) : month.abb
## [1]  1.4584104143  0.0007500051 -0.7629123322  0.2433415442  0.0052823403
FALSE ? rnorm(5) : month.abb
## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

(यह काम करता है क्योंकि पूर्ववर्ती की :तुलना में कम है ?।)

दुर्भाग्य से, यह तब मौजूदा मदद और अनुक्रम ऑपरेटरों को तोड़ता है।


5

बस एक मज़ाक के रूप में, आप कर सकते हैं फिर से परिभाषित ?करने के लिए (लगभग) त्रिगुट ऑपरेटर की तरह काम ऑपरेटर (यह एक बुरा विचार है):

`?` <- function(x, y) { y <-substitute(y); if(x) eval(y[[2]], parent.frame()) else eval(y[[3]], parent.frame()) }

x <- 1:3
length(x) ? (x*2) : 0
x <- numeric(0)
length(x) ? (x*2) : 0

for(i in 1:5) cat(i, (i %% 2) ? "Odd\n" : "Even\n")

... लेकिन आपको अभिव्यक्तियों को कोष्ठक में रखने की आवश्यकता है क्योंकि डिफ़ॉल्ट पूर्वता सी में पसंद नहीं है।

जब आप खेल कर रहे हों, तो पुराने सहायता फ़ंक्शन को पुनर्स्थापित करना याद रखें:

rm(`?`)

5

मैं ifelseकमान देखूंगा। मैं इसे और भी बेहतर कहूंगा क्योंकि यह सदिश भी है। कार डाटासेट का उपयोग कर एक उदाहरण:

> cars$speed > 20
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
[49]  TRUE  TRUE

> ifelse(cars$speed > 20, 'fast', 'slow')
 [1] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow"
[11] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow"
[21] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow"
[31] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow"
[41] "slow" "slow" "slow" "fast" "fast" "fast" "fast" "fast" "fast" "fast"

4
हाय पॉल - क्या आपका मतलब ifelseआपके उदाहरण से कुछ दिखाना है ? ;)
जोश ओ'ब्रायन 16

4

आपका लिंक एक ifस्टेटमेंट की ओर इशारा करता है।

> x <- 1
> if(x < 2) print("Less than") else print("Greater than")
[1] "Less than"

यदि आपका इनपुट चर एक वेक्टर है, तो ifelseअधिक उपयुक्त हो सकता है:

> x <- 1:3
> ifelse(x<=2, "Less than or equal", "Greater than")
[1] "Less than or equal" "Less than or equal" "Greater than"   

के लिए मदद पृष्ठ तक पहुँचने के लिए if, आपको ifबैकटिक्स में एम्बेड करना होगा :

?`if`

इसके लिए सहायता पृष्ठ यहां ifelseहै:

`?ifelse`

1
जैसा कि @kohske ने कहा, यह भी काम करेगा:print(if (x<2) "Less than" else "Greater than")
बेन बोल्कर

4

यह स्पष्ट रूप से मौजूद नहीं है, लेकिन आप यह कर सकते हैं:

set.seed(21)
y <- 1:10
z <- rnorm(10)

condition1 <- TRUE
x1 <- if(condition1) y else z

या

condition2 <- sample(c(TRUE,FALSE),10,TRUE)
x2 <- ifelse(condition2, y, z)

दोनों के बीच अंतर यह है कि condition1, लंबाई 1 के एक तार्किक वेक्टर होना चाहिए, जबकि condition2एक तार्किक वेक्टर के रूप में एक ही लंबाई होना चाहिए x, yऔर z। पहले या तो वापस आ जाएगी yया zजबकि दूसरे की इसी तत्व वापस आ जाएगी (संपूर्ण वस्तु), y( condition2==TRUE) या z( condition2==FALSE)।

भी ध्यान रखें कि ifelseकी तुलना में धीमी हो जाएगा if/ elseअगर condition, yऔर zलंबाई 1 के साथ सभी वैक्टर हैं।


धन्यवाद जोशुआ, आपके उत्तर से बहुत मदद मिली, मैंने पोस्ट से उत्तर पाया जिसका आपने उल्लेख किया है stackoverflow.com/a/8792474/3019570
महदी जदालिहा

2

if यदि निम्न तरीके से उपयोग किया जाता है, तो अनाकारित इफ्लेज़ जैसे कार्य:

`if`(condition, doIfTrue, doIfFalse)

आईफ्लेस पर इस का उपयोग करने का लाभ तब होता है जब वेक्टराइजेशन रास्ते में होता है (अर्थात मेरे पास स्केलर बूलियन और परिणाम के रूप में सूची / वेक्टर चीजें हैं)

ifelse(TRUE, c(1,2), c(3,4))
[1] 1
`if`(TRUE, c(1,2), c(3,4))
[1] 1 2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.