R 将字符串切分为固定宽度字符元素的向量
我有一个包含文本字符串的对象:R 将字符串切分为固定宽度字符元素的向量,r,strsplit,R,Strsplit,我有一个包含文本字符串的对象: x <- "xxyyxyxy" 看起来strsplit应该是我的票,但是因为我没有正则表达式foo,我不知道如何让这个函数按照我想要的方式将字符串切碎。我该怎么做呢?完全是黑客,JD,但它做到了 x <- "xxyyxyxy" c<-strsplit(x,"")[[1]] sapply(seq(2,nchar(x),by=2),function(y) paste(c[y-1],c[y],sep="")) [1] "xx" "yy" "xy" "
x <- "xxyyxyxy"
看起来strsplit应该是我的票,但是因为我没有正则表达式foo,我不知道如何让这个函数按照我想要的方式将字符串切碎。我该怎么做呢?完全是黑客,JD,但它做到了
x <- "xxyyxyxy"
c<-strsplit(x,"")[[1]]
sapply(seq(2,nchar(x),by=2),function(y) paste(c[y-1],c[y],sep=""))
[1] "xx" "yy" "xy" "xy"
x这里有一种方法,但不使用正则表达式:
a <- "xxyyxyxy"
n <- 2
sapply(seq(1,nchar(a),by=n), function(x) substr(a, x, x+n-1))
astrsplit会有问题,看看这样的regexp
strsplit(z, '[[:alnum:]]{2}')
它将在右边的点分裂,但没有留下任何东西
您可以使用子字符串和好友
z <- 'xxyyxyxy'
idx <- 1:nchar(z)
odds <- idx[(idx %% 2) == 1]
evens <- idx[(idx %% 2) == 0]
substring(z, odds, evens)
z怎么样
strsplit(gsub("([[:alnum:]]{2})", "\\1 ", x), " ")[[1]]
基本上,添加一个分隔符(此处为“”),然后使用strsplit
使用子字符串是最好的方法:
substring(x, seq(1, nchar(x), 2), seq(2, nchar(x), 2))
但plyr有一个解决方案:
library("plyr")
laply(seq(1, nchar(x), 2), function(i) substr(x, i, i+1))
下面是一个快速解决方案,它将字符串拆分为字符,然后将偶数元素和奇数元素粘贴在一起
x <- "xxyyxyxy"
sst <- strsplit(x, "")[[1]]
paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)])
x注意,对于子字符串,如果字符串长度不是请求长度的倍数,则在第二个序列中需要一个+(n-1):
substring(x,seq(1,nchar(x),n),seq(n,nchar(x)+n-1,n))
辅助函数:
fixed_split <- function(text, n) {
strsplit(text, paste0("(?<=.{",n,"})"), perl=TRUE)
}
fixed_split(x, 2)
[[1]]
[1] "xx" "yy" "xy" "xy"
fixed\u split好吧,我使用以下伪代码来完成这个任务:
在长度为n的每个块上插入一个特殊序列
按所述顺序拆分字符串
在代码中,我做到了
chopS <- function( text, chunk_len = 2, seqn)
{
# Specify select and replace patterns
insert <- paste("(.{",chunk_len,"})", sep = "")
replace <- paste("\\1", seqn, sep = "")
# Insert sequence with replaced pattern, then split by the sequence
interp_text <- gsub( pattern, replace, text)
strsplit( interp_text, seqn)
}
chopS这里有一个选项使用stringi::stri_sub()
。尝试:
x <- "xxyyxyxy"
stringi::stri_sub(x, seq(1, stringi::stri_length(x), by = 2), length = 2)
# [1] "xx" "yy" "xy" "xy"
<代码> x使用C++的速度更快。与之相比:
GSee GSee(x)4.2724.457541.74284.58554.71053702.289100
#>rstub(x)1.710 1.8990 139.40519 2.0665 2.1250 13722.075 100
种子(42)
x[1]正确
微基准:微基准(GSee(x),rstub(x))
#>单位:毫秒
#>expr最小lq平均uq最大neval
#>GSee(x)17.931801 18.431504 19.282877 18.738836 19.47943 27.191390 100
#>rstub(x)3.197587 3.261109 3.404973 3.341099 3.45852 4.872195 100
根据我的测试,下面的代码比以前的基准测试方法更快。stri_sub非常快,seq.int比seq好。通过将所有2L更改为其他值,也可以很容易地更改字符串的大小
library(stringi)
split_line <- function(x) {
row_length <- stri_length(x)
stri_sub(x, seq.int(1L, row_length, 2L), seq.int(2L, row_length, 2L))
}
库(stringi)
split_line如果要根据已知的计数按一定的间隔分割字符串,strsplit()适用于固定字符串或reg exp,但听起来像是要按长度分割吗?完全正确。我想根据长度来做。strsplit想要为delimiter匹配一个正则表达式,而我没有delimiter。两年后在stackoverflow.com中有一个更快的答案@我想你应该回答这个问题。这将是对答案的一个很好的补充。str_match_all(x,“{2}”)
这正是我编写的黑客代码。当然我要做一个循环而不是sapply;)这也是一种很好的方式。因为strsplit(x,“”)与我想要的非常接近,我想我让自己在思想上被srtsplit()所吸引。如果必须在3个字符后切掉字符串,子字符串将如何工作?看起来它只适用于2个字符的排印。只是为了增加通用性,如果我们想要每个n
字符而不是每2个字符,它应该是:子字符串(x,seq(1,nchar(x),n),seq(n,nchar(x),n))
你真是个天才!我使用<代码> X从Ralf Stubner的答案中尝试他的C++函数
fixed_split <- function(text, n) {
strsplit(text, paste0("(?<=.{",n,"})"), perl=TRUE)
}
fixed_split(x, 2)
[[1]]
[1] "xx" "yy" "xy" "xy"
chopS <- function( text, chunk_len = 2, seqn)
{
# Specify select and replace patterns
insert <- paste("(.{",chunk_len,"})", sep = "")
replace <- paste("\\1", seqn, sep = "")
# Insert sequence with replaced pattern, then split by the sequence
interp_text <- gsub( pattern, replace, text)
strsplit( interp_text, seqn)
}
x <- "xxyyxyxy"
stringi::stri_sub(x, seq(1, stringi::stri_length(x), by = 2), length = 2)
# [1] "xx" "yy" "xy" "xy"
GSee <- function(x) {
sst <- strsplit(x, "")[[1]]
paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)])
}
rstub <- Rcpp::cppFunction( code = '
CharacterVector strsplit2(const std::string& hex) {
unsigned int length = hex.length()/2;
CharacterVector res(length);
for (unsigned int i = 0; i < length; ++i) {
res(i) = hex.substr(2*i, 2);
}
return res;
}')
x <- "xxyyxyxy"
all.equal(GSee(x), rstub(x))
#> [1] TRUE
microbenchmark::microbenchmark(GSee(x), rstub(x))
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> GSee(x) 4.272 4.4575 41.74284 4.5855 4.7105 3702.289 100
#> rstub(x) 1.710 1.8990 139.40519 2.0665 2.1250 13722.075 100
set.seed(42)
x <- paste(sample(c("xx", "yy", "xy"), 1e5, replace = TRUE), collapse = "")
all.equal(GSee(x), rstub(x))
#> [1] TRUE
microbenchmark::microbenchmark(GSee(x), rstub(x))
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> GSee(x) 17.931801 18.431504 19.282877 18.738836 19.47943 27.191390 100
#> rstub(x) 3.197587 3.261109 3.404973 3.341099 3.45852 4.872195 100
library(stringi)
split_line <- function(x) {
row_length <- stri_length(x)
stri_sub(x, seq.int(1L, row_length, 2L), seq.int(2L, row_length, 2L))
}
split_line <- function(x) {
stri_sub(x, seq.int(1L, stri_length(x), 109L), length = 109L)
}