【问题标题】:Check if character value is a valid R object name检查字符值是否是有效的 R 对象名称
【发布时间】:2011-12-06 07:27:57
【问题描述】:

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

哦,是的,使用反引号之类的东西被认为是作弊。 =)

【问题讨论】:

  • 你可以试着用这个名字创建一个对象,看看它是否有效
  • 是的,tryCatch 非常接近最后一道防线。
  • 最后一道防线。为什么?完美解决你的问题。
  • @DavidHeffernan -- 不过要小心。 assign(" _jjj", 9) 毫无怨言地进行评估,即使 `_jjj` 在语法上无效...

标签: regex r naming-conventions


【解决方案1】:

于 2013 年 1 月 9 日编辑以修复正则表达式。 之前的正则表达式(摘自 John Chambers 的“数据分析软件”的第 456 页)(略)不完整。 (h.t. 哈德利·威克姆)


这里有几个问题。一个简单的正则表达式可用于识别所有语法上有效的名称 --- 但其中一些名称(如 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     
    ...   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
    

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

【讨论】:

  • 我很怀疑. 是一个有效的变量名,而且空格似乎也很疯狂。你确定不是他写的_,是在翻译中丢失了吗?
  • 啊——但是. 在语法上是有效的。试试. &lt;- 9 ; . 看看是不是。
  • 不只是...,甚至...呢? ... 有特殊含义,如果你先... &lt;- 4,然后get("..."),你会得到正确的响应。这确实比提供一些讨厌的正则表达式有点棘手。在这种特殊情况下,... 存储在.GlobalEnv 中,因此 R 不会对此大喊大叫。但是,如果您查看?Reserved,您也会在那里看到...。无论如何,没有人阻止你为几乎所有包含在反引号内的对象名称赋值。但是,无论如何,感谢您指向make.names。我喜欢! =)
  • @al3xa:从语法上讲,使用.... 作为变量名没有什么问题。 解析器赋予...一个特殊的含义。
  • make.names 是这样做的正确方法。我前段时间在 r-devel 上问过:r.789695.n4.nabble.com/Syntactically-valid-names-td3636819.html
【解决方案2】:

正如 Josh 所建议的,make.names 可能是解决此问题的最佳方法。它不仅会处理奇怪的标点符号,还会标记保留字:

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

【讨论】:

  • +1 -- 感谢您和您的 cmets。您确实帮助我将保留名称和未保留名称之间的区别归零(两者在语法上有效)。
猜你喜欢
  • 2020-10-15
  • 2011-01-31
  • 2016-10-18
  • 1970-01-01
  • 2018-03-21
  • 2011-11-08
  • 2020-08-20
  • 2017-10-22
  • 2017-03-29
相关资源
最近更新 更多