假设一个向量:
xx.1 <- c("zz_ZZ_uu_d", "II_OO_d")
我希望从最右边分割出一个新的向量,然后只拆分一次。预期结果将是:
c("zz_ZZ_uu", "d", "II_OO", "d").
这就像python的rsplit()
功能。我目前的想法是反转字符串,并将str_split()
与stringr
分开。
有更好的解决方案吗?
更新
这是我的解决方案返回n分裂,取决于stringr和stringi。有人提供带有基本功能的版本会很好。
rsplit <- function (x, s, n) {
cc1 <- unlist(stringr::str_split(stringi::stri_reverse(x), s, n))
cc2 <- rev(purrr::map_chr(cc1, stringi::stri_reverse))
return(cc2)
}
答案 0 :(得分:6)
否定前瞻:
unlist(strsplit(xx.1, "_(?!.*_)", perl = TRUE))
# [1] "zz_ZZ_uu" "d" "II_OO" "d"
a(?!b)
在哪里找到a
之后没有b
的{{1}}。在这种情况下,.*_
表示无论多远(.*
),都不应再有_
。
然而,概括这个想法似乎并不容易。首先,请注意,可以使用_(?=[^_]*$)
将其重写为正向前瞻(查找_
后跟除_
之外的任何内容,此处$
表示字符串的结尾)。那么一个不太优雅的概括就是
rsplit <- function(x, s, n) {
p <- paste0("[^", s, "]*")
rx <- paste0(s, "(?=", paste(rep(paste0(p, s), n - 1), collapse = ""), p, "$)")
unlist(strsplit(x, rx, perl = TRUE))
}
rsplit(vec, "_", 1)
# [1] "a_b_c_d_e_f" "g" "a" "b"
rsplit(vec, "_", 3)
# [1] "a_b_c_d" "e_f_g" "a_b"
例如如果n=3
此函数使用_(?=[^_]*_[^_]*_[^_]*$)
。
答案 1 :(得分:2)
"(.*)_(.*)"
作为模式来捕获字符串的两个部分。请记住,*
是贪婪的,因此第一个(.*)
将匹配尽可能多的字符。
在这里,我使用regexec
来捕捉您的断言开始和结束的位置,并regmatches
重新构建它们:
unlist(lapply(regmatches(xx.1, regexec("(.*)_(.*)", xx.1)),
tail, -1))
这一点不那么学术但很容易理解:
unlist(strsplit(sub("(.*)_(.*)", "\\1@@@\\2", xx.1), "@@@"))
答案 2 :(得分:1)
分裂之后将它粘贴在一起怎么样?
rsplit <- function( x, s ) {
spl <- strsplit( "zz_ZZ_uu_d", s, fixed=TRUE )[[1]]
res <- paste( spl[-length(spl)], collapse=s, sep="" )
c( res, spl[length(spl)] )
}
> rsplit("zz_ZZ_uu_d", "_")
[1] "zz_ZZ_uu" "d"
答案 3 :(得分:1)
我也想过与Ari非常类似的方法
> res <- lapply(strsplit(xx.1, "_"), function(x){
c(paste0(x[-length(x)], collapse="_" ), x[length(x)])
})
> unlist(res)
[1] "zz_ZZ_uu" "d" "II_OO" "d"
答案 4 :(得分:0)
这完全符合您的要求,是最简单的方法:
require(stringr)
as.vector(t(str_match(xx.1, '(.*)_(.*)') [,-1]))
[1] "zz_ZZ_uu" "d" "II_OO" "d"
说明:
str_split()
不是你正在寻找的机器人,因为它只是从左到右分裂,然后分裂然后重新播放所有(n-1)最左边的匹配是完全浪费时间。因此,将str_split()
与带有两个捕获组的正则表达式一起使用。请注意,第一个(.*)_
将贪婪地匹配最后一次出现_
的所有内容,这就是您想要的。 (如果至少有一个_
并且返回NAs,则会失败)str_match()
返回一个矩阵,其中第一列是整个字符串,后续列是各个捕获组。我们不想要第一列,因此请使用[,-1]
as.vector()
将按列显示该矩阵,这不是您想要的,因此我们使用t()
将其转置为逐行展开str_match(string, pattern)
在字符串和模式上进行矢量化,这是整洁的