【问题标题】:How to convert a vector of strings to Title Case如何将字符串向量转换为标题大小写
【发布时间】:2013-03-24 11:49:01
【问题描述】:

我有一个小写的字符串向量。我想将它们更改为标题大小写,这意味着每个单词的第一个字母都会大写。我已经设法用双循环来做到这一点,但我希望有一种更有效和更优雅的方式来做到这一点,也许是带有gsub 和正则表达式的单行。

这是一些示例数据,以及有效的双循环,以及我尝试过的其他无效的方法。

strings = c("first phrase", "another phrase to convert",
            "and here's another one", "last-one")

# For each string in the strings vector, find the position of each 
#  instance of a space followed by a letter
matches = gregexpr("\\b[a-z]+", strings) 

# For each string in the strings vector, convert the first letter 
#  of each word to upper case
for (i in 1:length(strings)) {

  # Extract the position of each regex match for the string in row i
  #  of the strings vector.
  match.positions = matches[[i]][1:length(matches[[i]])] 

  # Convert the letter in each match position to upper case
  for (j in 1:length(match.positions)) {

    substr(strings[i], match.positions[j], match.positions[j]) = 
      toupper(substr(strings[i], match.positions[j], match.positions[j]))
  }
}

这行得通,但看起来异常复杂。我只是在尝试更直接的方法失败后才使用它。以下是我尝试过的一些事情以及输出:

# Google search suggested \\U might work, but evidently not in R
gsub("(\\b[a-z]+)", "\\U\\1" ,strings)
[1] "Ufirst Uphrase"                "Uanother Uphrase Uto Uconvert"
[3] "Uand Uhere'Us Uanother Uone"   "Ulast-Uone"                   

# I tried this on a lark, but to no avail
gsub("(\\b[a-z]+)", toupper("\\1"), strings)
[1] "first phrase"              "another phrase to convert"
[3] "and here's another one"    "last-one"  

正则表达式捕获每个字符串中的正确位置,如调用gregexpr 所示,但替换字符串显然无法按预期工作。

如果您还不能确定,我对正则表达式比较陌生,希望能帮助您了解如何让替换正确工作。我还想学习如何构造正则表达式以避免在撇号后捕获一个字母,因为我不想更改这些字母的大小写。

【问题讨论】:

    标签: regex r replace


    【解决方案1】:

    主要问题是您缺少perl=TRUE(并且您的正则表达式略有错误,尽管这可能是为了解决第一个问题而四处乱窜的结果)。

    使用 [:lower:] 而不是 [a-z] 会稍微安全一些,以防您的代码最终在一些奇怪的 (sorry, Estonians) 语言环境中运行,其中 z 不是字母表的最后一个字母...

    re_from <- "\\b([[:lower:]])([[:lower:]]+)"
    strings <- c("first phrase", "another phrase to convert",
                 "and here's another one", "last-one")
    gsub(re_from, "\\U\\1\\L\\2" ,strings, perl=TRUE)
    ## [1] "First Phrase"              "Another Phrase To Convert"
    ## [3] "And Here's Another One"    "Last-One"    
    

    您可能更喜欢使用\\E(停止大写)而不是\\L(开始小写),具体取决于您要遵循的规则,例如:

    string2 <- "using AIC for model selection"
    gsub(re_from, "\\U\\1\\E\\2" ,string2, perl=TRUE)
    ## [1] "Using AIC For Model Selection"
    

    【讨论】:

    • 嗨@BenBolker,您的re_from 应该是"\\b([[:alpha:]])([[:alpha:]]+)" 而不是"\\b([[:lower:]])([[:lower:]]+)"。否则,在你最后的评论中使用\\E 是没有意义的。
    【解决方案2】:

    不使用regextolower 的帮助页面有两个示例函数可以做到这一点。

    更健壮的版本是

    capwords <- function(s, strict = FALSE) {
        cap <- function(s) paste(toupper(substring(s, 1, 1)),
                      {s <- substring(s, 2); if(strict) tolower(s) else s},
                                 sep = "", collapse = " " )
        sapply(strsplit(s, split = " "), cap, USE.NAMES = !is.null(names(s)))
    }
    capwords(c("using AIC for model selection"))
    ## ->  [1] "Using AIC For Model Selection"
    

    要让您的 regex 方法(几乎)正常工作,您需要设置 `perl = TRUE)

    gsub("(\\b[a-z]{1})", "\\U\\1" ,strings, perl=TRUE)
    
    
    [1] "First Phrase"              "Another Phrase To Convert"
    [3] "And Here'S Another One"    "Last-One"  
    

    但你可能需要更好地处理撇号

    sapply(lapply(strsplit(strings, ' '), gsub, pattern = '^([[:alnum:]]{1})', replace = '\\U\\1', perl = TRUE), paste,collapse = ' ')
    

    快速搜索SO发现https://stackoverflow.com/a/6365349/1385941

    【讨论】:

    • 遗憾的是,我对 SO 的不那么快速的搜索并没有出现您提到的问题。我尝试了“将字符串转换为标题大小写”、“将每个单词的首字母转换为大写”、“将每个单词的首字母大写”等,但不知何故没有找到神奇的搜索字符串。无论如何,我很高兴得到我的问题的答案,因为它们增加了一些选项和一些关于正则表达式如何工作的额外见解。
    【解决方案3】:

    这里已经有了很好的答案。这是使用报告包中的便利功能的一个:

    strings <- c("first phrase", "another phrase to convert",
        "and here's another one", "last-one")
    
    CA(strings)
    
    ## > CA(strings)
    ## [1] "First Phrase"              "Another Phrase To Convert"
    ## [3] "And Here's Another One"    "Last-one"       
    

    虽然它没有大写一个,因为对我的目的来说这样做没有意义。

    更新我管理具有TC(标题大小写)函数的qdapRegex包,该功能可以实现真正的标题大小写:

    TC(strings)
    
    ## [[1]]
    ## [1] "First Phrase"
    ## 
    ## [[2]]
    ## [1] "Another Phrase to Convert"
    ## 
    ## [[3]]
    ## [1] "And Here's Another One"
    ## 
    ## [[4]]
    ## [1] "Last-One"
    

    【讨论】:

      【解决方案4】:

      为了好玩,我会再添加一个:

      topropper(strings)
      [1] "First Phrase"              "Another Phrase To Convert" "And Here's Another One"   
      [4] "Last-one"  
      
      topropper <- function(x) {
        # Makes Proper Capitalization out of a string or collection of strings. 
        sapply(x, function(strn)
         { s <- strsplit(strn, "\\s")[[1]]
             paste0(toupper(substring(s, 1,1)), 
                   tolower(substring(s, 2)),
                   collapse=" ")}, USE.NAMES=FALSE)
      }
      

      【讨论】:

        【解决方案5】:

        这是另一个单行代码,基于stringr 包:

        str_to_title(strings, locale = "en")
        

        strings 是您的字符串向量。

        Source

        【讨论】:

          【解决方案6】:

          将任何情况转换为任何其他情况的最佳方法是在 r 中使用 snakecase 包。

          只需使用包

          library(snakecase)
          strings = c("first phrase", "another phrase to convert",
                  "and here's another one", "last-one")
          
          to_title_case(strings)
          
          ## [1] "First Phrase"              "Another Phrase to Convert" 
          ## [3] "And Here s Another One"    "Last One" 
          

          继续编码!

          【讨论】:

            猜你喜欢
            • 2010-11-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多