分割并细分字符串列表

时间:2019-08-09 07:26:03

标签: r regex string

我有一个字符串列表,其中不同的子字符串除以'_'字符,我想从此列表中获取特定的子字符串以形成新列表:

此字符串列表如下:

lista <- c('ORD_EVI_19870401_MAXI_002','CAB_EVI_19850301_MAXI_003','CAB_EVI_19850401_MAXI_001','PIC_EVI_19920301_MAXI_001','PIC_EVI_19920401_MAXI_003')

我知道这可行:

lista <-  substr(lista, 9,12)

我正在寻找输出:

[1] "1987" "1985" "1985" "1992" "1992"

但是有时每个字符串的长度都不同,所以不起作用。

如何组合strsplitsubstr函数以获取列表中每个元素中第三个子字符串的前四个字符?

4 个答案:

答案 0 :(得分:2)

一种方法可能是:

substr(sapply(strsplit(list, "_", fixed = TRUE), "[", 3), 1, 4)

[1] "1987" "1985" "1985" "1992" "1992"

或者使用tstrsplit()中的data.table

sapply(tstrsplit(list, "_", fixed = TRUE, keep = 3), substr, 1, 4)

只是方法的一小部分比较:

library(microbenchmark)

lst <- rep(list, 100000)

microbenchmark(
 tmfmnk_strsplit = substr(sapply(strsplit(lst, "_", fixed = TRUE), "[", 3), 1, 4),
 tmfmnk_tstrsplit = sapply(tstrsplit(lst, "_", fixed = TRUE, keep = 3), substr, 1, 4),
 Ronak_Shah_strsplit = sapply(strsplit(lst, "_"), function(x) substr(x[3], 1, 4)),
 Ronak_Shah_sub = sub("^(?:[^_]+_){2}(.{4}).*", "\\1", lst),
 Sotos_stringr_word = substr(stringr::word(lst, 3, 3, sep = '_'), 1, 4),
 Sotos_gsub = substr(gsub("\\D+", "", lst), 1, 4),
 patL_1 = str_sub(str_split(lst, pattern = "_", simplify = TRUE)[,3], start = 1, end = 4),
 patL_2 = str_split(lst, pattern = "_", simplify = TRUE)[,3] %>% str_sub(start = 1, end = 4), 
 times = 5
)

Unit: milliseconds
                expr       min        lq      mean    median         uq        max neval
     tmfmnk_strsplit  600.8501  615.2786  688.7693  618.1062   631.8959   977.7155     5
    tmfmnk_tstrsplit  383.7881  392.2930  596.2255  428.4289   445.8589  1330.7584     5
 Ronak_Shah_strsplit 4372.1978 4436.3701 4650.4455 4551.9226  4652.0911  5239.6461     5
      Ronak_Shah_sub  737.3849  756.7462  773.2315  759.4766   777.2293   835.3204     5
  Sotos_stringr_word 8298.2679 8459.3475 9452.5748 9954.5619 10255.8447 10294.8522     5
          Sotos_gsub 1299.2949 1323.2183 1479.6777 1386.1354  1446.8309  1942.9089     5
              patL_1  730.1206  731.3955  842.6071  813.4897   841.1782  1096.8517     5
              patL_2  635.8529  656.1035  818.8592  669.6658   713.0357  1419.6380     5

答案 1 :(得分:2)

另一个想法是使用gsub,即

substr(gsub('\\D+', '', list), 1, 4)
#[1] "1987" "1985" "1985" "1992" "1992"

还有stringr程序包和(总是很有趣的)函数word,即

substr(stringr::word(list, 3, 3, sep = '_'), 1, 4)
#[1] "1987" "1985" "1985" "1992" "1992"

答案 2 :(得分:2)

使用scanf的另一种方法:

stringr

或相同,但传递代码:

library(stringr)

str_sub(str_split(list, pattern = "_", simplify = TRUE)[,3],
        start = 1,
        end = 4)

#[1] "1987" "1985" "1985" "1992" "1992"

答案 3 :(得分:1)

我们可以在"_"上分割字符串,并提取第三部分的前4个字符。

sapply(strsplit(lista, "_"), function(x) substr(x[3], 1, 4))
#[1] "1987" "1985" "1985" "1992" "1992"

或者从here那里获得帮助的完整正则表达式解决方案

sub("^(?:[^_]+_){2}(.{4}).*", "\\1", lista)
#[1] "1987" "1985" "1985" "1992" "1992"

这将提取第二个下划线后的前4个字符。