R语言 提取字符串的一部分并将其粘贴到其他“组”中

s4n0splo  于 11个月前  发布在  其他
关注(0)|答案(4)|浏览(124)

这里我有一个简单的字符串;

input_string <- "P24928 [1909-1922]; [1923-1936]; P08775 [1909-1922]; [1923-1936]"

字符串
我希望它将第一部分,即P#####,粘贴在第二组括号之前,这样字符串将是:

"P24928 [1909-1922]; P24928 [1922-1923]; P08775 [1909-1922]; P08775 [1922-1923]"

u91tlkcl

u91tlkcl1#

我们可以使用gregexpr来找到P*\s-regmatches。我们希望它们作为一个空格和一个空格之间的空值的替代品。我们可以使用``regmatches<-()函数有效地做到这一点(也可以用学分来淋浴 @thelatemail!)。

> f <- \(x) {
+   sbs <- regmatches(x, gregexpr(r"{P\d+\s(?=\[)}", x, perl=TRUE))
+   mtc <- gregexpr(r"{(?<=;\s)(?=\[)}", x, perl=TRUE)
+   regmatches(x, mtc) <- sbs
+   x
+ }
> f(x)
[1] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"

字符串
请注意,这已经是矢量化,即您可以执行以下操作,

> f(c(x, x, x))
[1] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"
[2] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"
[3] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"


顺便说一句,在R之外处理这样的任务可能更有效。如果我们使用awk,并且假设我们有一个文本文件 foo.txt,其行格式为x,我们可以这样处理它:

$ awk -v OFS=' ' '{print $1, $2, $1 FS $3, $4, $5, $4 FS $6}' foo.txt
P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]
P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]
P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]

  • 数据类型:*
x <- "P24928 [1909-1922]; [1923-1936]; P08775 [1909-1922]; [1923-1936]"

iqxoj9l9

iqxoj9l92#

library(tidyverse)

input_string <- "P24928 [1909-1922]; [1923-1936]; P08775 [1909-1922]; [1923-1936]"

parts <- input_string |> 
  str_split_1("\\s") |> 
  str_remove(";$")

parts |> 
  matrix(ncol = 3, byrow = TRUE) |> 
  as.data.frame() |> 
  mutate(str_c(V1, " ", V2, "; ", V1, " ", V3, "; ")) |> 
  pull(last_col()) |> 
  str_flatten() |> 
  str_remove(";\\s+$")
#> [1] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"

字符串
创建于2023-12-10使用reprex v2.0.2

olmpazwi

olmpazwi3#

这里还有一个:

library(tidyverse)

input_string %>% 
  as_tibble() %>% 
  separate_rows(value, sep = " ") %>% 
  group_by(group =as.integer(gl(n(),3,n()))) %>% 
  mutate(x = paste(first(value), value)) %>% 
  filter(grepl("\\[", x)) %>% 
  pull() %>% 
  paste(., collapse = " ")

个字符

v440hwme

v440hwme4#

下面是一个使用正则表达式的更简洁的解决方案:

library(tidyverse)
as.data.frame(input_string) %>%
  separate_rows(input_string, sep = "(?<=;)\\s(?=[A-Z])") %>%
  mutate(input_string = str_replace_all(input_string, "(\\w+)(.*?;)(.*$)", "\\1\\2 \\1\\3")) %>%
  summarise(input_string = str_c(input_string, collapse = " "))
# A tibble: 1 × 1
  input_string                                                                  
  <chr>                                                                         
1 P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]

字符串
我们首先使用正向后看将字符串分成组((?<=;))和前瞻项((?=[A-Z])),它们实现了一条指令,在左边有一个空格,右边有一个大写字母的空白处进行分隔。然后我们将得到的字符串定义为三个捕获组,我们使用反向引用\\1\\2,和\\3将第一个子字符串粘贴到第二个子字符串之后。最后,我们将分离的部分折叠回单个字符串。

编辑

如果你的字符串总是有六个子字符串和两个“组”,就像例子中那样,那么一个简单的一行代码就足够了:

str_replace_all(input_string, "(\\w+)(.*?;)(.*?;) (\\w+)(.*?;)(.*?$)", "\\1\\2 \\1\\3 \\4\\5 \\4\\6")
[1] "P24928 [1909-1922]; P24928 [1923-1936]; P08775 [1909-1922]; P08775 [1923-1936]"


当然,这种解决方案可以适用于每组更多的元素和更多的组。

相关问题