gpt4 book ai didi

r - 排序包含语义版本的字符向量

转载 作者:行者123 更新时间:2023-12-04 11:29:52 25 4
gpt4 key购买 nike

似乎是一个非常基本的问题,但我真的想不出一个“简单”的方法来做到这一点。

我想用 基础 R 功能 对包含 semantic version numberscharacter 向量进行排序:

vsns  <- c("1", "10", "1.1", "1.10", "1.2", "1.1.1", 
"1.1.10", "1.1.2", "1.1.1.1", "1.1.1.10", "1.1.1.2")

排序后应该是这样的:
# [1] "1"        "1.1"      "1.1.1"    "1.1.1.1"  "1.1.1.2"  "1.1.1.10"
# [7] "1.1.2" "1.1.10" "1.2" "1.10" "10"

这当然不能满足我的要求,因为 R 只是按字母顺序对整个内容进行排序:
sort(vsns)
# [1] "1" "1.1" "1.1.1" "1.1.1.1" "1.1.1.10" "1.1.1.2" "1.1.10"
# [8] "1.1.2" "1.10" "1.2" "10"
vsns[order(vsns)]
# [1] "1" "1.1" "1.1.1" "1.1.1.1" "1.1.1.10" "1.1.1.2" "1.1.10"
# [8] "1.1.2" "1.10" "1.2" "10"

尝试规范化它(有点沿着这个 post ),但我想不出适合语义版本结构的匹配/替换方案:
tmp <- gsub("\\.", "", vsns)
# [1] "011" "021" "0101" "0201"
tmp_nchar <- sapply(tmp, nchar)
to_add <- max(tmp_nchar) - tmp_nchar
tmp <- sapply(1:length(tmp), function(ii) {
paste0(tmp[ii], paste(rep("A", to_add[ii]), collapse = ""))
})
# [1] "10" "1.10" "1.1.10" "1.1.1.10" "1.1.1.1" "1.1.1.2" "1.1.1"
# [8] "1.1.2" "1.1" "1.2" "1"
vsns[order(tmp)]
# [1] "1AAAA" "10AAA" "11AAA" "110AA" "12AAA" "111AA" "1110A" "112AA" "1111A" "11110"
# [11] "1112A"

到目前为止我能想到的最好的就是这个,但它看起来很漂亮......参与;-)
sortVersionNumbers <- function(x, decreasing = FALSE) {
tmp <- strsplit(x, split = "\\.")
tmp_l <- sapply(tmp, length)
idx_max <- which.max(tmp_l)[1]
tmp_l_max <- tmp_l[idx_max]
tmp_n <- lapply(tmp, function(ii) {
ii_l <- length(ii)
if (ii_l < tmp_l_max) {
c(ii, rep(NA, (tmp_l_max - ii_l)))
} else {
ii
}
})
tmp <- matrix(as.numeric(unlist(tmp_n)), nrow = length(tmp_n), byrow = TRUE)
tmp_cols <- ncol(tmp)
expr <- paste0("order(", paste(paste0("tmp[,", 1:tmp_cols, "]"),
collapse = ", "), ", na.last = FALSE",
ifelse(decreasing, ", decreasing = FALSE)", ")"))
idx <- eval(parse(text = expr))
tmp_2 <- tmp[idx,]
sapply(1:nrow(tmp_2), function(ii) {
paste(na.omit(tmp_2[ii,]), collapse = ".")
})
}
sortVersionNumbers(vsns)
# [1] "1" "1.1" "1.1.1" "1.1.1.1" "1.1.1.2" "1.1.1.10" "1.1.2"
# [8] "1.1.10" "1.2" "1.10" "10"
sortVersionNumbers(sort(vsns))
# [1] "1" "1.1" "1.1.1" "1.1.1.1" "1.1.1.2" "1.1.1.10" "1.1.2"
# [8] "1.1.10" "1.2" "1.10" "10"

最佳答案

从 ? numeric_version

> sort(numeric_version(vsns))
[1] '1' '1.1' '1.1.1' '1.1.1.1' '1.1.1.2' '1.1.1.10'
[7] '1.1.2' '1.1.10' '1.2' '1.10' '10'

看看这是如何实现的相对有趣。 numeric_version 将单个版本字符串拆分为整数部分,并将版本向量存储为整数向量列表。 xtfrm 上的一个方法(由 sort() 使用)将构成每个版本字符串的整数向量转换为一个数值,其中的胆量是
base <- max(unlist(x), 0, na.rm = TRUE) + 1                                 
x <- vapply(x, function(t) sum(t/base^seq.int(0, length.out = length(t))),
1)

结果是一个数值向量,可用于以标准方式对原始向量进行排序。因此,临时解决方案是
xtfrm.my_version <- function(x) {
x <- lapply(strsplit(x, ".", fixed=TRUE), as.integer)
base <- max(unlist(x), 0, na.rm = TRUE) + 1
vapply(x, function(t) sum(t/base^seq.int(0, length.out = length(t))), 1)
}

vsns <- c("1", "10", "1.1", "1.10", "1.2", "1.1.1",
"1.1.10", "1.1.2", "1.1.1.1", "1.1.1.10", "1.1.1.2")
class(vsns) = "my_version"
sort(vsns)

关于r - 排序包含语义版本的字符向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26034308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com