【问题标题】:Regular expression to extract first word + first character of all following words正则表达式提取第一个单词+所有后续单词的第一个字符
【发布时间】:2020-02-14 09:17:56
【问题描述】:

我是(新手)使用 R 和正则正则表达式来编写用于在 data.frame 列中操作字符串的正则表达式。我的数据在 R 中如下所示:

c1                       
Peter Parker            
Hawk & Dove             
J Jonah Jameson         
3JPX spo                
Bruce Wayne              

我想要得到的是包含以下字符串的第二列“c2”:

c2
PeterP
Hawk&D
JJJ
3JPXs
BruceW

基本上我想要字符串的整个第一个单词(不管长度)和之后每个单词的第一个字母数字元素。我无法为此找到任何功能或逻辑。可以用正则表达式这样做吗?

提前致谢

【问题讨论】:

  • 顺便说一句,你的意思是c2 来自c1,还是打错字?
  • 是的。我希望列 c2 中的值来自列 c1 中的值
  • 啊,列名。我不认为那是data.framematrix。有时,以更明确的格式提供数据(例如以编程方式使用data.frame(...)dput(x))既有用(对我们而言)又绝对清晰;虽然后者看起来不那么棒,但它可以用最少的努力(就我们而言)给出一个完全相同的对象。
  • 我确实说过这是问题标题中的 data.frame 列。但下次我也会使用“data.frame(...)”表示法。 :) 谢谢
  • 对我不好,谢谢。 (我发现多行标题有点忙,所以我一定是浏览得太快了。下次我会努力的:-)

标签: r regex


【解决方案1】:

这是使用 gsub 的基本 R 方法:

x <- c("Peter Parker", "Hawk & Dove", "J Jonah Jameson", "3JPX spo", "Bruce Wayne")
output <- gsub("\\s+(\\S)\\S*(?!\\S)", "\\1", x, perl=TRUE)
output

[1] "PeterP" "Hawk&D" "JJJ"    "3JPXs"  "BruceW"

正则表达式模式\s+(\S)\S*(?!\S) 匹配一个或多个空格字符,然后匹配并捕获名称组件的第一个字符。它还消耗名称组件的其余部分,仅替换为捕获的第一个字符。

如果您仍然不清楚上述内容,请逐步说明正则表达式模式的工作原理:

\s+    match one or more space characters
(\S)   then match AND capture the first character of the name-word
\S*    match the remainder of the name-word
(?!\S) assert that what follows the end of the name-word is either a space
       or the end of the string

gsub 的调用中的替换只是\1,这是第一个也是唯一一个捕获组,对应于每个名字的第一个字母,除了第一个名字。

【讨论】:

  • 感谢这个完美的作品。只是出于好奇-它可以处理的字符串中的字数是否有字数限制?
  • 我不确定我是否关注您的评论。您能否向我展示当前输入之一以及您希望它在新要求下的外观?
  • 例如 - Albus Percival Wulfric Brian Dumbledore -> AlbusPWBD。上述方法是否也适用于 5 个单词或更长的字符串?
  • @JohnR 是的,它适用于由任意数量的名称单词组成的名称。试试看。 gsub 中的 g 表示“全局”替换,因此它涵盖了所有单词。
  • JohnR,你试过了吗?尤其是在 Tim 的解决方案如此简短的情况下,使用该名称尝试它比输入问题花费的时间更少……然后你必须等待回复。
【解决方案2】:

虽然不是一个特别的正则表达式解决方案,但另一种方法可能是通过分隔每个单词以获取长格式的数据,按原样获取第一个单词,并从剩余的单词中仅取出第一个字符并粘贴它们。

library(dplyr)

df %>%
  group_by(row = row_number()) %>%
  tidyr::separate_rows(c1, sep = "\\s+") %>%
  summarise(c2 = paste0(first(c1) , paste0(substr(c1[-1], 1, 1), collapse = "")),
            c1 = paste(c1, collapse = " ")) %>%
  select(c1, c2, -row)

#   c1              c2    
#  <chr>           <chr> 
#1 Peter Parker    PeterP
#2 Hawk & Dove     Hawk&D
#3 J Jonah Jameson JJJ   
#4 3JPX spo        3JPXs 
#5 Bruce Wayne     BruceW

数据

df <- structure(list(c1 = c("Peter Parker", "Hawk & Dove", "J Jonah Jameson", 
"3JPX spo", "Bruce Wayne")), row.names = c(NA, -5L), class = "data.frame")

【讨论】:

    【解决方案3】:

    unglue 的开发版本有一个multiple 参数,它可以是一个应用于同名匹配的函数(这里我们希望将它们与paste0() 连接起来)。在我们的例子中,我们想要匹配完整的第一个单词,然后是所有序列的第一个字符,由空格分隔,并且我们在第一个单词之后有 1 个或 2 个这样的序列:

    # remotes::install_github("moodymudskipper/unglue")
    library(unglue)
    patterns <- c(
      "{c2} {c2=\\S}{=\\S*} {c2=\\S}{=\\S*}",
      "{c2} {c2=\\S}{=\\S*}")
    
    unglue_data(df$c1, patterns, multiple = paste0)
    #>       c2
    #> 1 PeterP
    #> 2 Hawk&D
    #> 3    JJJ
    #> 4  3JPXs
    #> 5 BruceW  
    

    【讨论】:

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