it-swarm.com.de

Mehrere Muster abgleichen

Ich möchte sehen, ob "001" oder "100" oder "000" in einer Zeichenfolge von 4 Zeichen aus 0 und 1 vorkommt. Eine aus 4 Zeichen bestehende Zeichenfolge könnte beispielsweise "1100" oder "0010" oder "1001" oder "1111" sein. Wie kann ich mit einem einzigen Befehl viele Zeichenfolgen in einer Zeichenfolge abgleichen? 

Ich weiß, dass Grep für die Mustererkennung verwendet werden kann. Mit Grep kann ich jedoch immer nur eine Zeichenfolge überprüfen. Ich möchte wissen, ob mehrere Zeichenfolgen mit einem anderen Befehl oder mit grep selbst verwendet werden können.

20
Narayani

Ja, du kannst. Der | in einem grep-Muster hat dieselbe Bedeutung wie or. So können Sie Ihr Muster testen, indem Sie "001|100|000" als Muster verwenden. Gleichzeitig wird grep vektorisiert, sodass dies alles in einem Schritt erfolgen kann: 

x <- c("1100", "0010", "1001", "1111")
pattern <- "001|100|000"

grep(pattern, x)
[1] 1 2 3

Dies gibt einen Index zurück, von dem Ihre Vektoren das übereinstimmende Muster enthielten (in diesem Fall die ersten drei).

Manchmal ist es praktischer, einen logischen Vektor zu haben, der Ihnen mitteilt, welche der Elemente in Ihrem Vektor übereinstimmen. Dann können Sie grepl verwenden:

grepl(pattern, x)
[1]  TRUE  TRUE  TRUE FALSE

Siehe ?regex für Hilfe zu regulären Ausdrücken in R.


Edit: Um das manuelle Erstellen von Mustern zu vermeiden, können Sie paste verwenden:

myValues <- c("001", "100", "000")
pattern <- paste(myValues, collapse = "|")
40
Andrie

Hier ist eine Lösung, die das Paket stringr verwendet

require(stringr)
mylist = c("1100", "0010", "1001", "1111")
str_locate(mylist, "000|001|100")
7
Ramnath

Verwenden Sie das Argument -e, um weitere Muster hinzuzufügen:

echo '1100' | grep -e '001' -e '110' -e '101'
3
Patrick Dignan

Sie können auch den Operator %like% aus der Bibliothek data.table verwenden.

library(data.table)

# input
  x <- c("1100", "0010", "1001", "1111")
  pattern <- "001|100|000"

# check for pattern
  x %like% pattern

> [1]  TRUE  TRUE  TRUE FALSE
1
rafa.pereira

Wenn Sie einen logischen Vektor wünschen, sollten Sie die stri_detect-Funktion aus dem stringi-Paket überprüfen. In Ihrem Fall ist das Muster regex, also verwenden Sie dieses:

stri_detect_regex(x, pattern)
## [1]  TRUE  TRUE  TRUE FALSE

Und einige Benchmarks:

require(microbenchmark)
test <- stri_paste(stri_Rand_strings(100000, 4, "[0-1]"))
head(test)
## [1] "0001" "1111" "1101" "1101" "1110" "0110"
microbenchmark(stri_detect_regex(test, pattern), grepl(pattern, test))
Unit: milliseconds
                             expr      min       lq     mean   median       uq      max neval
 stri_detect_regex(test, pattern) 29.67405 30.30656 31.61175 30.93748 33.14948 35.90658   100
             grepl(pattern, test) 36.72723 37.71329 40.08595 40.01104 41.57586 48.63421   100
1
bartektartanus

Es tut uns leid, dass Sie dies zu einer zusätzlichen Antwort gemacht haben, aber es sind zu viele Zeilen für einen Kommentar. 

Ich möchte nur daran erinnern, dass die Anzahl der Elemente, die zusammen über paste(..., collapse = "|") eingefügt werden können, um als einzelnes übereinstimmendes Muster verwendet zu werden, begrenzt ist - siehe unten. Vielleicht kann jemand sagen, wo genau das Limit liegt? Zwar ist die Anzahl zwar nicht realistisch, sollte aber je nach auszuführender Aufgabe nicht vollständig von unseren Überlegungen ausgeschlossen werden.

Für eine wirklich große Anzahl von Elementen wäre eine Schleife erforderlich, um jedes Element des Musters zu überprüfen.

set.seed(0)
samplefun <- function(n, x, collapse){
  paste(sample(x, n, replace=TRUE), collapse=collapse)
}

words <- sapply(rpois(10000000, 8) + 1, samplefun, letters, '')
text <- sapply(rpois(1000, 5) + 1, samplefun, words, ' ')

#since execution takes a while, I have commented out the following lines

#result <- grepl(paste(words, collapse = "|"), text)

# Error in grepl(pattern, text) : 
#   invalid regular expression 
# 'wljtpgjqtnw|twiv|jphmer|mcemahvlsjxr|grehqfgldkgfu|
# ...

#result <- stringi::stri_detect_regex(text, paste(words, collapse = "|"))

# Error in stringi::stri_detect_regex(text, paste(words, collapse = "|")) : 
# Pattern exceeds limits on size or complexity. (U_REGEX_PATTERN_TOO_BIG)
0
Manuel Bickel