Select 字符串中的每第 n 个字符

Select every nth character from a string

我有一串带有随机空格和一些句点的随机字母。我想 从中取出第 n 个值 (例如,每第 10 个)。我的想法是,如果我可以转置它,那么我可以对每个第 n 个值使用 select 的行号。感谢您的帮助!

string <- "hutmnycdsldzlkt.ytairuaypk  dq.gubgp hyfjuwvpcdmvqxfcuhapnx"

我们可以拆分字符串并使用seq获取元素

v1 <- strsplit(string, "")[[1]]
v1[seq(1, by = 10, length(v1))]
#[1] "h" "d" "r" "." "j" "x"

或使用正则表达式环顾四周

library(stringr)
str_replace_all(string, "(.).{1,9}", "\1")
#[1] "hdr.jx"

或者使用 glue

使其动态化
n <- 9
str_replace_all(string, glue::glue("(.).{1,[n]}",
          .open = '[', .close = ']'), "\1")
#[1] "hdr.jx"

substring 将采用 first=last= 的向量,因此我们可以形成适当的序列并从那里开始。

func <- function(x, n, start = 1) {
  vapply(x, function(z) {
    i <- seq.int(start, nchar(z), by = n)
    i <- i[i > 0]
    paste(substring(x, i, i), collapse = "")
  }, character(1))
}

func(string, 10)
# hutmnycdsldzlkt.ytairuaypk  dq.gubgp hyfjuwvpcdmvqxfcuhapnx 
#                                                    "hdr.jx" 

其中每 10 个(从 1 个开始)是

hutmnycdsldzlkt.ytairuaypk  dq.gubgp hyfjuwvpcdmvqxfcuhapnx 
12345678901234567890123456789012345678901234567890123456789
^         ^         ^         ^         ^         ^
h         d         r         .         j         x

(我使用 apply 变体的最大原因是万一你有一个字符串向量,其中 substring 可以优雅地工作。)

跟进 OP 的想法(“使用行号”)。拆分字符串,用 10 行填充一个矩阵,select 第一行。

matrix(strsplit(x, "")[[1]], nrow = 10)[1, ]
# [1] "h" "d" "r" "." "j" "x"

您会收到回收警告,但这不会影响我们,因为我们 select 第一行。


好东西charToRaw:

rawToChar(charToRaw(x)[c(TRUE, rep(FALSE, 9))])
# [1] "hdr.jx"

使用 substring + seq + nchar

的基础 R 选项
substring(
  string,
  v <- seq(1, nchar(string), by = 10),
  v
)

给予

"h" "d" "r" "." "j" "x"

好的,这是对 @r2evans 的回答的补充,它试图通过不必在每个单独的值上循环来加速矢量化 substring 操作。

func2 <- function(x, n, start = 1) {
    mnc <- max(nchar(x))
    i <- seq.int(start, mnc, by = n)
    res <- paste(substring(rep(x, each=length(i)), i, i), collapse="")
    fi <- findInterval(nchar(x), i)
    substring(res, c(1, head(cumsum(fi),-1) + 1), cumsum(fi) )
}   

20K 条记录的快速测试:

x <- c("12345678901234567890", "09876543210987654321")
bigx <- rep(x,1e4)

system.time(func(bigx, 10, 1))
##   user  system elapsed 
##  38.29    0.03   38.36 

system.time(func2(bigx, 10, 1))
## user  system elapsed 
## 0.02    0.00    0.02