检查字符值是否是有效的R对象名称

时间:2011-12-06 07:27:58

标签: regex r naming-conventions

几个月前我asked something similar,但我使用JavaScript来检查提供的字符串是否是“有效”的R对象名称。现在我想通过使用除了R之外的任何东西来实现同样的目标。我想有一个非常好的方法来做这个,有一些整洁的(不那么)深奥的R函数,所以正则表达式在我看来是最后一道防线。有什么想法吗?

哦,是的,使用背蜱和东西被认为是作弊。 =)

2 个答案:

答案 0 :(得分:9)

编辑2013-1-9修正正则表达式。以前的正则表达式,从约翰钱伯斯的“数据分析软件”第456页解除,(巧妙地)不完整。 (h.t. Hadley Wickham)


这里有几个问题。可以使用简单的正则表达式来标识所有语法上有效的名称 - 但其中一些名称(如ifwhile)是“保留的”,并且无法分配。

  • 识别语法上有效的名称:

?make.names解释了语法上有效的名称:

  

[...]由字母,数字和字母组成   点或下划线字符,以字母或点开头   没有跟着一个数字。诸如“.2way”之类的名称无效[...]

这是相应的正则表达式:

  "^([[:alpha:]]|[.][._[:alpha:]])[._[:alnum:]]*$"
  • 识别无保留语法上有效的名称

要识别非保留名称,您可以利用基函数make.names(),它从任意字符串构造语法上有效的名称。

    isValidAndUnreserved <- function(string) {
        make.names(string) == string
    }

    isValidAndUnreserved(".jjj")
    # [1] TRUE
    isValidAndUnreserved(" jjj")
    # [1] FALSE
  • 全部放在一起

    isValidName <- function(string) {
        grepl("^([[:alpha:]]|[.][._[:alpha:]])[._[:alnum:]]*$", string)
    }
    
    isValidAndUnreservedName <- function(string) {
        make.names(string) == string
    }
    
    testValidity <- function(string) {
        valid <- isValidName(string)
        unreserved <- isValidAndUnreservedName(string)
        reserved <- (valid & ! unreserved)
        list("Valid"=valid,
             "Unreserved"=unreserved,
             "Reserved"=reserved)
    }
    
    testNames <- c("mean", ".j_j", "...", "if", "while", "TRUE", "NULL",
                   "_jj", "  j", ".2way") 
    t(sapply(testNames, testValidity))
    
          Valid Unreserved Reserved
    mean  TRUE  TRUE       FALSE   
    .j_j  TRUE  TRUE       FALSE   
    ...   TRUE  TRUE       FALSE   
    if    TRUE  FALSE      TRUE    
    while TRUE  FALSE      TRUE    
    TRUE  TRUE  FALSE      TRUE    
    NULL  TRUE  FALSE      TRUE    
    _jj   FALSE FALSE      FALSE   
      j   FALSE FALSE      FALSE   # Note: these tests are for "  j", not "j"
    .2way FALSE FALSE      FALSE  
    

有关这些问题的更多讨论,请参阅以下评论中由@Hadley链接的the r-devel thread

答案 1 :(得分:5)

正如Josh所说,make.names可能是最好的解决方案。它不仅会处理奇怪的标点符号,还会标记保留字:

make.names(".x")   # ".x"
make.names("_x")   # "X_x"
make.names("if")   # " if."
make.names("function")  # "function."