2016-04-26 63 views
0

以下函數採用長度爲1或2的字符向量x,並檢查它是否包含變量a和b中的字符串 - 注意x不應該包含a和b在同一個元素中。 然後它返回a或b或兩者。 有沒有更乾淨的方法來做到這一點?R中的模式匹配有兩種模式和一個列表輸入

match_vec <- function(x, a = "alpha", b = "beta") { 
    stopifnot(is.character(x), is.character(a), is.character(b)) 
    stopifnot(length(a) == 1, length(b) == 1) 
    stopifnot(length(x) %in% c(1, 2)) 
    ai <- grep(a, x) 
    bi <- grep(b, x) 
    if (length(x) == 1) { 
    if (length(ai) == 1 && length(bi) == 0) { 
     return(a) 
    } else if (length(ai) == 0 && length(bi) == 1) { 
     return(b) 
    } else { 
     stop(paste("Could not find", a, "xor", b, "in:", x)) 
    } 
    } 
    if (length(x) == 2) { 
    if (length(ai) == 1 && length(bi) == 1) { 
     stopifnot(ai != bi) 
     return(c(a, b)) 
    } else { 
     stop(paste("Could not find both", a, "and", b, "in:", x, collapse = "\n")) 
    } 
    } 
} 


match_vec(c("alpha", "beta")) 
#[1] "alpha" "beta" 
match_vec(c("beta", "alpha")) 
#[1] "alpha" "beta" 
match_vec("alpha") 
#[1] "alpha" 
match_vec("betaaaa") 
#[1] "beta" 
match_vec("bettaaaa") 
#Error in match_vec("bettaaaa") : 
# Could not find alpha xor beta in: bettaaaa 
match_vec("alphaandbeta") 
#Error in match_vec("alphaandbeta") : 
# Could not find alpha xor beta in: alphaandbeta 
match_vec(c("this has thealpha", "beta in here")) 
#[1] "alpha" "beta" 
+0

你可以改變第二'if'到'else_if'。提高性能一點。 –

回答

2

有很多的停止和檢查功能相當直接的行動。

這裏有一個選擇:

match_vec<-function(n) sapply(c("alpha", "beta"), function(x) grep(x, n, value=T)) 

match_vec(c("alpha", "beta")) 
    alpha beta 
"alpha" "beta" 

match_vec(c("beta", "alpha")) 
    alpha beta 
"alpha" "beta" 

match_vec("alpha") 
$alpha 
[1] "alpha" 

$beta 
character(0) 

match_vec("betaaaa") 
$alpha 
character(0) 

$beta 
[1] "betaaaa" 

match_vec("bettaaaa") 
$alpha 
character(0) 

$beta 
character(0) 
+0

謝謝你。檢查功能用於處理特定情況。例如,用你的答案,你將如何檢查你是否得到了一個字符(0)的輸出?你需要重寫函數並分別處理每個案例。 – PeterQ

+0

瞭解。你的代碼其實很好。看起來很混亂,但我不認爲這個表演真的會對循環造成影響。 –