2016-04-26 12 views
0

Die folgende Funktion nimmt einen Zeichenvektor x der Länge 1 oder 2 und prüft, ob sie die Zeichenfolgen in Variablen a und b enthält - beachten Sie, dass x kein a haben soll und b im selben Element. Es gibt dann a oder b oder beides zurück. Gibt es einen saubereren Weg, dies zu tun?Mustererkennung in R mit zwei Mustern und einer Listeneingabe

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

Sie können den zweiten 'ändern if' zu' else_if'. Die Leistung ein wenig verbessern. –

Antwort

2

Es gibt eine Menge von Stop und Prüffunktionen für eine ziemlich geradlinig Aktion.

Hier ist eine Alternative:

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

Danke dafür. Die Check-Funktionen sind dazu da, um bestimmte Fälle zu behandeln. Wie würden Sie zum Beispiel mit Ihrer Antwort prüfen, ob Sie eine Ausgabe mit Zeichen (0) erhalten? Sie müssten die Funktion neu schreiben und jeden Fall separat behandeln. – PeterQ

+0

Verstanden. Dein Code ist in Ordnung. Sieht chaotisch aus, aber ich denke nicht, dass die Performance wirklich einen Strich durch die Loops macht. –