簡體   English   中英

比strsplit()在R中將字符串拆分為兩個更有效的內存方式

[英]More memory efficient way than strsplit() to split a string into two in R

我有一個1.8米的字符串,我需要將它分成一個50字符的字符串,該字符串非常接近1.8m字符串的開頭(大約10k個字符)

使用strsplit()錯誤

long_string %>% strsplit(., fifty_character_string)

# Error: C stack usage  9065064 is too close to the limit

我試圖用這種方法解決具體的錯誤, 這個問題,但到目前為止沒有運氣。

所以現在我正在調查是否有一種更有效的內存方法將一個非常長的字符串拆分成兩個字符串。 我不太可能需要這么做很多次,所以我對那些完成工作的hacky方法持開放態度

以下是對不同方法的快速比較:

library(stringi)
library(dplyr)

# get some sample data
set.seed(1)
long_string <- stri_paste(stri_rand_lipsum(10000), collapse = " ")
x <- sample(9000:11000, 1)
split_string <- substr(long_string, x, x + 49)

result <- long_string %>% strsplit(., split_string)
length(unlist(result))
#> [1] 2

substr_fun <- function(str, pattern) {
  idx <- regexpr(pattern, str, fixed = TRUE)
  res1 <- list(c(substr(str, 1, idx-1), substr(str, idx + attr(idx, "match.length"), nchar(str))))
  return(res1)  
}

bench::mark(
  strsplit_dplyr = long_string %>% strsplit(., split_string),
  strsplit_dplyr_fixed = long_string %>% strsplit(., split_string, fixed = TRUE),
  strsplit = strsplit(long_string, split_string),
  strsplit_fixed = strsplit(long_string, split_string, fixed = TRUE),
  stri_split_fixed = stringi::stri_split_fixed(long_string, split_string),
  str_split = stringr::str_split(long_string, stringr::fixed(split_string)),
  substr_fun = substr_fun(long_string, split_string)
)
#> # A tibble: 7 x 6
#>   expression                min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>           <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 strsplit_dplyr          131ms  134.8ms      7.44      280B        0
#> 2 strsplit_dplyr_fixed   36.6ms   37.6ms     26.5       280B        0
#> 3 strsplit                133ms  133.8ms      7.40        0B        0
#> 4 strsplit_fixed         35.4ms   37.2ms     26.7         0B        0
#> 5 stri_split_fixed       40.7ms   42.5ms     23.6     6.95KB        0
#> 6 str_split              41.6ms   43.1ms     23.4    35.95KB        0
#> 7 substr_fun             13.6ms   14.8ms     67.1         0B        0

在內存使用方面,使用選項fixed = TRUE並且沒有管道開銷的strsplit是最佳解決方案。 stringistringr的實現似乎要快一點,但它們在內存方面的開銷甚至比管道的效果還要大。

更新

我從@H 1回答中添加了方法,並且還使用了他的方法來獲取用於分割的50個字符的子字符串。 只有改變是我將它包裝在一個函數中並再次添加fixed = TRUE ,因為我認為在這種情況下更有意義。

如果您不想在字符串中進行多次拆分,則新功能是明顯的贏家!

因為字符串只能被分成兩個,所以有效的方法是使用regexpr()substr()

# Generate string (10m char) and pattern
set.seed(10)
long_string <- paste0(sample(letters, 1e+7, replace = TRUE), collapse ="")
x <- sample(9000:11000, 1)
fifty_character_string <- substr(long_string, x, x + 49)

# Find index and split
idx <- regexpr(fifty_character_string, long_string)
res1 <- list(c(substr(long_string, 1, idx-1), substr(long_string, idx + attr(idx, "match.length"), nchar(long_string))))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM