Test if characters are in a string
我试图确定一个字符串是否是另一个字符串的子集。例如:
1 2 | chars <-"test" value <-"es" |
如果"value"作为字符串"chars"的一部分出现,我想返回true。在下面的场景中,我希望返回false:
1 2 | chars <-"test" value <-"et" |
使用
1 2 | grepl(value, chars) # TRUE |
回答
叹息,我花了45分钟才找到这个简单问题的答案。答案是:
1 2 3 4 5 6 7 8 9 10 11 | # 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 |
解释
现在,
但是,回到你最初的问题,我们真正想要的是知道我们是否在干草堆中找到了针,一个正确/错误的值。他们显然决定将这个函数命名为
所以,现在我们知道这个名字是从哪里来的,应该怎么做。让我们回到正则表达式。这些参数,即使它们是字符串,也用于构建正则表达式(从此:regex)。regex是一种匹配字符串的方法(如果这个定义让您不快,就让它走吧)。例如,regex
所以,如果你在没有设置
你的代码越好,你就越不需要了解历史来理解它。每个参数至少可以有两个有趣的值(否则它不需要是一个参数),docs在这里列出了9个参数,这意味着至少有2^9=512种方法可以调用它,这是大量的编写、测试和记住工作…分离这样的函数(将它们分开,消除相互依赖关系,字符串的内容与regex不同,而向量的内容不同)。有些选项也是互斥的,不要给用户错误的代码使用方法,即有问题的调用在结构上应该是无意义的(例如传递一个不存在的选项),而不是逻辑上的无意义的(必须发出警告来解释它)。打个比方:把10楼的前门换成墙总比挂一个警告不要使用的标志要好,但两者都不如。在一个接口中,函数定义参数应该是什么样子的,而不是调用方(因为调用方依赖于函数,推断出每个人可能都想用它调用的所有内容,使得函数也依赖于调用方,并且这种类型的循环依赖性将很快阻塞系统,并且永远不会提供任何好处。你期待)。小心模棱两可的类型,像
你要的是
1 2 3 4 5 6 7 8 | > chars <-"test" > value <-"es" > grepl(value, chars) [1] TRUE > chars <-"test" > value <-"et" > grepl(value, chars) [1] FALSE |
使用
1 2 | > stri_detect_fixed("test",c("et","es")) [1] FALSE TRUE |
一些基准:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 |
为了防止您还要检查一个字符串(或一组字符串)是否包含多个子字符串,您还可以在两个子字符串之间使用""。
1 2 3 | >substring="as|at" >string_vector=c("ass","ear","eye","heat") >grepl(substring,string_vector) |
你会得到
1 | [1] TRUE FALSE FALSE TRUE |
因为第一个字有子串"as",最后一个字有子串"at"
此外,还可以使用"stringer"库:
1 2 3 4 5 6 7 8 9 10 | > 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 |
使用
默认情况下,
1 2 3 | > grep("[","abc[") Error in grep("[","abc[") : invalid regular expression '[', reason 'Missing ']'' |
要进行真正的子串测试,请使用
1 2 | > grep("[","abc[", fixed = TRUE) [1] 1 |
如果你真的想要Regex,太好了,但这不是OP想要的。
您可以使用
1 2 3 4 | grep("es","Test") [1] 1 grep("et","Test") integer(0) |