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)
    }