Подтвердить что ты не робот

Измельчение строки в вектор символьных элементов с фиксированной шириной

У меня есть объект, содержащий текстовую строку:

x <- "xxyyxyxy"

и я хочу превратить это в вектор с каждым элементом, содержащим две буквы:

[1] "xx" "yy" "xy" "xy"

похоже, что strsplit() должен быть моим билетом, но поскольку у меня нет регулярного выражения foo, я не могу понять, как заставить эту функцию нарезать строку так, как я ее хочу. Как мне это сделать?

4b9b3361

Ответ 1

Использование подстроки - лучший подход:

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

Ответ 2

Как насчет

strsplit(gsub("([[:alnum:]]{2})", "\\1 ", x), " ")[[1]]

В принципе, добавьте разделитель (здесь ""), а затем используйте strsplit

Ответ 3

Вот быстрое решение, которое разбивает строку на символы, затем вставляет вместе четные элементы и нечетные элементы.

x <- "xxyyxyxy"
sst <- strsplit(x, "")[[1]]
paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)])

Настройка производительности:

library(microbenchmark)

GSee <- function(x) {
  sst <- strsplit(x, "")[[1]]
  paste0(sst[c(TRUE, FALSE)], sst[c(FALSE, TRUE)])
}

Shane1 <- function(x) {
  substring(x, seq(1,nchar(x),2), seq(2,nchar(x),2))
}

library("plyr")
Shane2 <- function(x) {
  laply(seq(1,nchar(x),2), function(i) substr(x, i, i+1))
}

seth <- function(x) {
  strsplit(gsub("([[:alnum:]]{2})", "\\1 ", x), " ")[[1]]
}

geoffjentry <- function(x) {
  idx <- 1:nchar(x)  
  odds <- idx[(idx %% 2) == 1]  
  evens <- idx[(idx %% 2) == 0]  
  substring(x, odds, evens)  
}

drewconway <- function(x) {
  c<-strsplit(x,"")[[1]]
  sapply(seq(2,nchar(x),by=2),function(y) paste(c[y-1],c[y],sep=""))
}

KenWilliams <- function(x) {
  n <- 2
  sapply(seq(1,nchar(x),by=n), function(xx) substr(x, xx, xx+n-1))
}

RichardScriven <- function(x) {
  regmatches(x, gregexpr("(.{2})", x))[[1]]
}

Тест 1:

x <- "xxyyxyxy"

microbenchmark(
  GSee(x),
  Shane1(x),
  Shane2(x),
  seth(x),
  geoffjentry(x),
  drewconway(x),
  KenWilliams(x),
  RichardScriven(x)
)

# Unit: microseconds
#               expr      min        lq    median        uq      max neval
#            GSee(x)    8.032   12.7460   13.4800   14.1430   17.600   100
#          Shane1(x)   74.520   80.0025   84.8210   88.1385  102.246   100
#          Shane2(x) 1271.156 1288.7185 1316.6205 1358.5220 3839.300   100
#            seth(x)   36.318   43.3710   45.3270   47.5960   67.536   100
#     geoffjentry(x)    9.150   13.5500   15.3655   16.3080   41.066   100
#      drewconway(x)   92.329   98.1255  102.2115  105.6335  115.027   100
#     KenWilliams(x)   77.802   83.0395   87.4400   92.1540  163.705   100
#  RichardScriven(x)   55.034   63.1360   65.7545   68.4785  108.043   100

Бенчмарк 2:

Теперь, с большими данными.

x <- paste(sample(c("xx", "yy", "xy"), 1e5, replace=TRUE), collapse="")

microbenchmark(
  GSee(x),
  Shane1(x),
  Shane2(x),
  seth(x),
  geoffjentry(x),
  drewconway(x),
  KenWilliams(x),
  RichardScriven(x),
  times=3
)

# Unit: milliseconds
#               expr          min            lq       median            uq          max neval
#            GSee(x)    29.029226    31.3162690    33.603312    35.7046155    37.805919     3
#          Shane1(x) 11754.522290 11866.0042600 11977.486230 12065.3277955 12153.169361     3
#          Shane2(x) 13246.723591 13279.2927180 13311.861845 13371.2202695 13430.578694     3
#            seth(x)    86.668439    89.6322615    92.596084    92.8162885    93.036493     3
#     geoffjentry(x) 11670.845728 11681.3830375 11691.920347 11965.3890110 12238.857675     3
#      drewconway(x)   384.863713   438.7293075   492.594902   515.5538020   538.512702     3
#     KenWilliams(x) 12213.514508 12277.5285215 12341.542535 12403.2315015 12464.920468     3
#  RichardScriven(x) 11549.934241 11730.5723030 11911.210365 11989.4930080 12067.775651     3

Ответ 4

strsplit будет проблематичным, посмотрите на регулярное выражение, подобное этому

strsplit(z, '[[:alnum:]]{2}')  

он будет разбит в правильных точках, но ничего не останется.

Вы можете использовать подстроку и друзей

z <- 'xxyyxyxy'  
idx <- 1:nchar(z)  
odds <- idx[(idx %% 2) == 1]  
evens <- idx[(idx %% 2) == 0]  
substring(z, odds, evens)  

Ответ 5

Общий взломать, 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"

Ответ 6

Здесь один путь, но не использование regexen:

a <- "xxyyxyxy"
n <- 2
sapply(seq(1,nchar(a),by=n), function(x) substr(a, x, x+n-1))

Ответ 7

ВНИМАНИЕ с подстрокой, если длина строки не кратная вашей запрошенной длине, вам понадобится + (n-1) во второй последовательности:

substring(x,seq(1,nchar(x),n),seq(n,nchar(x)+n-1,n)) 

Ответ 8

Вспомогательная функция:

fixed_split <- function(text, n) {
  strsplit(text, paste0("(?<=.{",n,"})"), perl=TRUE)
}

fixed_split(x, 2)
[[1]]
[1] "xx" "yy" "xy" "xy"

Ответ 9

Ну, для выполнения этой задачи я использовал следующий псевдокод:

  • Вставьте специальную последовательность на каждом фрагменте длины 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)
}

Это возвращает список с разделенным вектором внутри, но не вектором.