2016-04-26 34 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

了解。你的代码其实很好。看起来很混乱,但我不认为这个表演真的会对循环造成影响。 –