如何用R语言正则表达式实现文件路径的多级数字排序?
文件路径的层级化自然排序问题
我有数百个.wav文件,通过list.files()函数导入后得到如下文件路径列表:
[1] "10/Project_English-10/BL-0001_A-conifer-cone-contains-seeds/Balsam-poplar-English-0701.wav" [2] "10/Project_English-10/BL-0001_A-conifer-cone-contains-seeds/Birch-English-0700.wav" [3] "10/Project_English-10/BL-0001_A-conifer-cone-contains-seeds/Blueberry-English-0703.wav" ....... [73] "3/Project_English-3/BL-0002_Lesser-horseshoe-bat/Capercaillie-English-0069.wav" [74] "3/Project_English-3/BL-0002_Lesser-horseshoe-bat/Fat-tail-scorpion-English-0082.wav" [75] "3/Project_English-3/BL-0002_Lesser-horseshoe-bat/Fire-salamander-English-0067.wav"
我尝试用以下代码排序:
filename <- file_list[order(as.numeric(stringr::str_extract(file_list,"[0-9]+(.*?)")) )]
但这段代码只能让路径首个数字按数值排序(比如3开头的路径排在10开头之前),无法让最后一个子路径中的数字(如English-0067、English-0069)也按数值顺序排列。单独匹配最后一个子路径的数字排序又会打乱已有的路径层级顺序,请问如何实现所有子路径中的数字均按数值顺序排序?
解决方案:实现层级化自然排序
方法1:使用第三方包快速解决
R的gtools包提供了mixedsort()函数,能自动识别路径中每个分段的数字,按数值大小排序,同时保留路径层级顺序:
- 安装并加载包:
install.packages("gtools") library(gtools)
- 执行排序:
filename <- mixedsort(file_list)
这个函数会先按最上层目录的数字(3 < 10)排序,同一目录下按子目录的数字(BL-0001 < BL-0002),最后按文件名里的数字(English-0067 < English-0069 < English-0082),完全满足需求。
方法2:自定义函数实现无依赖排序
如果不想依赖第三方包,可以自己生成多层排序键:
# 生成自然排序的分段键 natural_sort_key <- function(x) { # 拆分字符串为文本和数字交替片段 parts <- strsplit(x, "(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)", perl = TRUE)[[1]] # 将数字片段转为数值,文本片段保留原样 sapply(parts, function(p) { if(grepl("^\\d+$", p)) as.numeric(p) else p }) } # 生成排序键矩阵,按层级排序 sort_keys <- do.call(rbind, lapply(file_list, natural_sort_key)) filename <- file_list[do.call(order, as.data.frame(sort_keys))]
这段代码会把每个路径拆分成文本和数字片段,将这些片段作为多层排序依据,实现和mixedsort()一致的效果。
内容的提问来源于stack exchange,提问作者Pengcheng Lai
相关产品推荐
相关产品推荐

