403 Stimmen

Prüfen, ob Zeichen in einer Zeichenkette enthalten sind

Ich versuche zu bestimmen, ob eine Zeichenfolge eine Teilmenge einer anderen Zeichenfolge ist. Zum Beispiel:

chars <- "test"
value <- "es"

Ich möchte zurückkehren TRUE wenn " value " erscheint als Teil der Zeichenfolge " chars ". In dem folgenden Szenario würde ich false zurückgeben wollen:

chars <- "test"
value <- "et"

562voto

smu Punkte 8487

Verwenden Sie die grepl fonction

grepl( needle, haystack, fixed = TRUE)

etwa so:

grepl(value, chars, fixed = TRUE)
# TRUE

Utilice ?grepl um mehr darüber zu erfahren.

234voto

Joshua Cheek Punkte 28392

Antwort

Seufz, ich habe 45 Minuten gebraucht, um die Antwort auf diese einfache Frage zu finden. Die Antwort ist: grepl(needle, haystack, fixed=TRUE)

# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE

# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE

Auslegung

grep ist nach der ausführbaren Linux-Datei benannt, die selbst ein Akronym für " G lobal R egular E xpression P rint", würde es die Eingabezeilen lesen und dann ausgeben, wenn sie mit den angegebenen Argumenten übereinstimmen. "Global" bedeutete, dass die Übereinstimmung überall in der Eingabezeile vorkommen konnte. Ich werde "Regulärer Ausdruck" weiter unten erklären, aber die Idee ist, dass es ein intelligenterer Weg ist, die Zeichenkette abzugleichen (R nennt dies "Zeichen", z.B. class("abc") ) und "Print", weil es sich um ein Kommandozeilenprogramm handelt, das in seine Ausgabezeichenfolge druckt.

Nun, die grep Programm ist im Grunde ein Filter, von Eingabe- zu Ausgabezeilen. Und es scheint, dass R's grep Funktion nimmt ebenfalls ein Array von Eingaben entgegen. Aus Gründen, die mir völlig unbekannt sind (ich habe erst vor etwa einer Stunde angefangen, mit R zu spielen), gibt sie einen Vektor der übereinstimmenden Indizes zurück, statt einer Liste von Übereinstimmungen.

Aber zurück zu Ihrer ursprünglichen Frage: Was wir wirklich wissen wollen, ist, ob wir die Nadel im Heuhaufen gefunden haben, ein wahrer oder falscher Wert. Sie haben offenbar beschlossen, diese Funktion zu nennen grepl wie bei "grep", aber mit einem " L ogischen" Rückgabewert (sie nennen true und false logische Werte, z.B. class(TRUE) ).

Jetzt wissen wir also, woher der Name stammt und was er bewirken soll. Kommen wir zurück zu den regulären Ausdrücken. Die Argumente, auch wenn sie Zeichenketten sind, werden verwendet, um reguläre Ausdrücke (im Folgenden: regex) zu bilden. Ein Regex ist eine Möglichkeit, eine Zeichenkette abzugleichen (wenn Sie diese Definition irritiert, lassen Sie es sein). Zum Beispiel kann der Regex a entspricht dem Zeichen "a" die Regex a* entspricht dem Zeichen "a" 0 oder mehr Mal, und die Regex a+ würde mit dem Zeichen "a" 1 oder mehrere Male. Im obigen Beispiel suchen wir also nach der Nadel 1+2 bedeutet als Regex "eine oder mehrere 1 gefolgt von einer 2"... aber auf unsere folgt ein Plus!

1+2 as a regex

Wenn Sie also die grepl ohne Einstellung fixed Ihre Nadeln wären versehentlich Heuhaufen, und das würde versehentlich ziemlich oft funktionieren, wie wir sehen können, funktioniert es sogar für das Beispiel des Auftraggebers. Aber das ist ein verborgener Fehler! Wir müssen dem Programm sagen, dass die Eingabe eine Zeichenkette und kein Regex ist, was anscheinend der Fall ist. fixed ist für. Warum fixiert? Keine Ahnung, merken Sie sich diese Antwort, denn Sie werden sie wahrscheinlich noch 5 Mal nachschlagen müssen, bevor Sie sie auswendig können.

Ein paar abschließende Gedanken

Je besser Ihr Code ist, desto weniger Geschichte müssen Sie kennen, um ihn zu verstehen. Jedes Argument kann mindestens zwei interessante Werte haben (sonst bräuchte es kein Argument zu sein), die Dokumentation listet hier 9 Argumente auf, was bedeutet, dass es mindestens 2^9=512 Möglichkeiten gibt, es aufzurufen, das ist eine Menge Arbeit zu schreiben, zu testen und sich zu merken... entkoppeln Sie solche Funktionen (teilen Sie sie auf, entfernen Sie Abhängigkeiten voneinander, String-Dinge sind anders als Regex-Dinge sind anders als Vektor-Dinge). Einige der Optionen schließen sich auch gegenseitig aus, geben Sie den Benutzern keine falschen Möglichkeiten, den Code zu verwenden, d.h. der problematische Aufruf sollte strukturell unsinnig sein (z.B. Übergabe einer Option, die nicht existiert), nicht logisch unsinnig (wo man eine Warnung ausgeben muss, um es zu erklären). Um es metaphorisch auszudrücken: Es ist besser, die Eingangstür im 10. Stock durch eine Wand zu ersetzen, als ein Schild aufzuhängen, das vor ihrer Benutzung warnt, aber beides ist besser als nichts. In einer Schnittstelle definiert die Funktion, wie die Argumente aussehen sollen, nicht der Aufrufer (da der Aufrufer von der Funktion abhängt, macht die Ableitung von allem, was jeder jemals aufrufen möchte, die Funktion auch von den Aufrufern abhängig, und diese Art von zyklischer Abhängigkeit wird ein System schnell verstopfen und nie die erwarteten Vorteile bringen). Seien Sie sehr vorsichtig mit zweideutigen Typen, es ist ein Designfehler, dass Dinge wie TRUE y 0 y "abc" sind alle Vektoren.

43voto

Justin Punkte 41677

Sie wollen grepl :

> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE

42voto

Surya Punkte 9736

Kann auch durchgeführt werden unter Verwendung der Bibliothek "stringr":

> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE

### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1]  TRUE FALSE  TRUE FALSE  TRUE

36voto

bartektartanus Punkte 14061

Verwenden Sie diese Funktion von stringi Paket:

> stri_detect_fixed("test",c("et","es"))
[1] FALSE  TRUE

Einige Benchmarks:

library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)

chars <- "es"
library(microbenchmark)
microbenchmark(
   grepl(chars, value),
   grepl(chars, value, fixed=TRUE),
   grepl(chars, value, perl=TRUE),
   stri_detect_fixed(value, chars),
   stri_detect_regex(value, chars)
)
## Unit: milliseconds
##                               expr       min        lq    median        uq       max neval
##                grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530   100
##  grepl(chars, value, fixed = TRUE)  5.071617  5.110779  5.281498  5.523421 45.243791   100
##   grepl(chars, value, perl = TRUE)  1.835558  1.873280  1.956974  2.259203  3.506741   100
##    stri_detect_fixed(value, chars)  1.191403  1.233287  1.309720  1.510677  2.821284   100
##    stri_detect_regex(value, chars)  6.043537  6.154198  6.273506  6.447714  7.884380   100

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X