5

次のカンマ区切りの数字列について考えてみましょう。

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"
4

4 に答える 4

3

私は遅すぎました...しかし、ここに別の解決策があります。

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"
于 2013-06-04T08:17:49.660 に答える
0

これがあなたが望むことをするべき関数です:

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"
于 2013-06-04T07:45:34.033 に答える