次のカンマ区切りの数字列について考えてみましょう。
s <- "1,2,3,4,8,9,14,15,16,19"
s
# [1] "1,2,3,4,8,9,14,15,16,19"
連続する数値の実行を対応する範囲に折りたたむことは可能ですか。たとえば、1,2,3,4
上記の実行は range に折りたたまれます1-4
。望ましい結果は、次の文字列のようになります。
s
# [1] "1-4,8,9,14-16,19"
次のカンマ区切りの数字列について考えてみましょう。
s <- "1,2,3,4,8,9,14,15,16,19"
s
# [1] "1,2,3,4,8,9,14,15,16,19"
連続する数値の実行を対応する範囲に折りたたむことは可能ですか。たとえば、1,2,3,4
上記の実行は range に折りたたまれます1-4
。望ましい結果は、次の文字列のようになります。
s
# [1] "1-4,8,9,14-16,19"
私は遅すぎました...しかし、ここに別の解決策があります。
R固有の関数をあまり使用しないため、他の言語に移植できます(一方で、エレガントではないかもしれません)
s <- "1,2,3,4,8,9,14,15,16,19"
collapseConsecutive <- function(s){
x <- as.numeric(unlist(strsplit(s, ",")))
x_0 <- x[1]
out <- toString(x[1])
hasDash <- FALSE
for(i in 2:length(x)) {
x_1 <- x[i]
x_2 <- x[i+1]
if((x_0 + 1) == x_1 && !is.na(x_2) && (x_1 + 1) == x_2) {
if(!hasDash) {
out <- c(out, "-")
hasDash <- TRUE
}
} else {
if(hasDash) {
hasDash <- FALSE
} else {
out <- c(out, ",")
}
out <- c(out, x_1)
hasDash <- FALSE
}
x_0 <- x_1
}
outString <- paste(out, collapse="")
outString
}
collapseConsecutive(s)
# [1] "1-4,8,9,14-16,19"
これがあなたが望むことをするべき関数です:
conseq <- function(s){
s <- as.numeric(unlist(strsplit(s, ",")))
dif <- s[seq(length(s))][-1] - s[seq(length(s)-1)]
new <- !c(0, dif == 1)
cs <- cumsum(new)
res <- vector(mode="list", max(cs))
for(i in seq(res)){
s.i <- s[which(cs == i)]
if(length(s.i) > 2){
res[[i]] <- paste(min(s.i), max(s.i), sep="-")
} else {
res[[i]] <- as.character(s.i)
}
}
paste(unlist(res), collapse=",")
}
> s <- "1,2,3,4,8,9,14,15,16,19"
> conseq(s)
[1] "1-4,8,9,14-16,19"