R 4.4.0 OS X Colleagues I have a sequence like: 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20 I would like to display it as: 1, 3-5, 7-8, 12-15, 20 Any simple ways to accomplish this? Dennis Dennis Fisher MD P < (The "P Less Than" Company) Phone / Fax: 1-866-PLessThan (1-866-753-7784) www.PLessThan.com [[alternative HTML version deleted]]
Hi Dennis, A quick Claude request: "using r I have a sequence like: 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20I would like to display it as: 1, 3-5, 7-8, 12-15, 20" yielded: condense_sequence <- function(nums) { if (length(nums) == 0) return("") if (length(nums) == 1) return(as.character(nums)) # Sort the numbers just in case they're not in order nums <- sort(unique(nums)) # Initialize variables ranges <- vector("character") start <- nums[1] prev <- nums[1] for (i in 2:length(nums)) { if (nums[i] != prev + 1) { # End of a sequence if (start == prev) { ranges <- c(ranges, as.character(start)) } else { ranges <- c(ranges, paste(start, prev, sep="-")) } start <- nums[i] } prev <- nums[i] } # Handle the last number or range if (start == prev) { ranges <- c(ranges, as.character(start)) } else { ranges <- c(ranges, paste(start, prev, sep="-")) } # Join all ranges with commas paste(ranges, collapse=", ") } # Your sequence nums <- c(1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20) # Apply the function result <- condense_sequence(nums) print(result) # Output: "1, 3-5, 7-8, 12-15, 20" Which appears to work well, though you may have other thoughts in mind / edge cases this code does not cover. Best, Steven On Fri, Feb 21, 2025 at 7:47?PM Dennis Fisher <fisher at plessthan.com> wrote:> R 4.4.0 > OS X > > Colleagues > > I have a sequence like: > 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20 > > I would like to display it as: > 1, 3-5, 7-8, 12-15, 20 > > Any simple ways to accomplish this? > > Dennis > > > Dennis Fisher MD > P < (The "P Less Than" Company) > Phone / Fax: 1-866-PLessThan (1-866-753-7784) > www.PLessThan.com > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
Cute exercise! "Simple" is in the eyes of the beholder, of course. There is probably a package out there that can do this in a trice . But my first thought -- so caveat emptor!, as my thoughts, first or last, are often not so, um... thoughtful -- is to diff() the sequence (as numerics) -- so that differences of 1 appears as identical -- and then make use of rle(). I think that one should be able to tweak this appropriately to make it work, but I leave the details to you (and to me as something to keep the little gray cells from atrophying). Note that somewhere along the line, you'll have to convert numerics to character, as "-" is obviously not going to cut it as a numeric. :-) Cheers, Bert Bert "An educated person is one who can entertain new ideas, entertain others, and entertain herself." On Fri, Feb 21, 2025 at 4:46?PM Dennis Fisher <fisher at plessthan.com> wrote:> R 4.4.0 > OS X > > Colleagues > > I have a sequence like: > 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20 > > I would like to display it as: > 1, 3-5, 7-8, 12-15, 20 > > Any simple ways to accomplish this? > > Dennis > > > Dennis Fisher MD > P < (The "P Less Than" Company) > Phone / Fax: 1-866-PLessThan (1-866-753-7784) > www.PLessThan.com > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
Dennis, You are supposedly using a vector containing integers, in order, and want to find sequences to rewrite compactly based on your example. What result do you want. An integer vector cannot hold something like 3-5 so do you want an integer of character stringls like this: c("1", "3-5", "7-8", "12-15", "20") Or do you want a single string like: "1, 3-5, 7-8, 12-15, 20" Or do you want other more exotic things like slices that might not actually be simpler or shorter. There may well be such functionality available, perhaps in some package, but you probably could easily roll your own for the first alternatives. Consider a function, perhaps recursive, which checks the first item in a vector and loops as long as it has not reached the end and checks if the next integer is one more. As soon as it changes, or the end is reached, take the subset of indices from first to last and bundle them to attach as one unit to what you have so far. The can mean making a string like first-last to add as one unit to a growing vector or at the end of a growing string. If you are doing this recursively, call the function again on a truncated version of the original input containg the so-far unused parts as something to attach to what you already have. This may not be the simple functionality you want so I looked for packages. This one may be close: install.packages("denstrip") library(denstrip) seqToIntervals(c(1:10, 15:18, 20)) from to 1 1 10 2 15 18 3 20 20 It is a matrix of stop/start and can be converted to your format with a little work or by using some parts of the source code for yourself and at a point, substituting in your format. It may take work if you get something like this:> apply(ranges, 1, paste, sep="-")1 2 3 "c(1, 10)" "c(15, 18)" "c(20, 20)" You might then use something like grep's substitute to replace "c(" and ")" with nothing and a "," by a "-" and so on. The package description is here, and there may well be other better ones: https://search.r-project.org/CRAN/refmans/denstrip/html/seqToIntervals.html -----Original Message----- From: R-help <r-help-bounces at r-project.org> On Behalf Of Dennis Fisher Sent: Friday, February 21, 2025 7:46 PM To: r-help <r-help at r-project.org> Subject: [R] Compressing a sequence R 4.4.0 OS X Colleagues I have a sequence like: 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20 I would like to display it as: 1, 3-5, 7-8, 12-15, 20 Any simple ways to accomplish this? Dennis Dennis Fisher MD P < (The "P Less Than" Company) Phone / Fax: 1-866-PLessThan (1-866-753-7784) www.PLessThan.com [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide https://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
?s 00:46 de 22/02/2025, Dennis Fisher escreveu:> R 4.4.0 > OS X > > Colleagues > > I have a sequence like: > 1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20 > > I would like to display it as: > 1, 3-5, 7-8, 12-15, 20 > > Any simple ways to accomplish this? > > Dennis > > > Dennis Fisher MD > P < (The "P Less Than" Company) > Phone / Fax: 1-866-PLessThan (1-866-753-7784) > www.PLessThan.com > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide https://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.Hello, Here is a way with package R.utils, function seqToIntervals. x <- scan(text = "1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20", sep = ",") mat <- R.utils::seqToIntervals(x) apply(mat, 1L, \(m) { ifelse(m[1L] == m[2L], m[1L], paste(m, collapse = "-")) }) #> [1] "1" "3-5" "7-8" "12-15" "20" If you want to be fancy, define a special class that prints like that. x <- scan(text = "1, 3, 4, 5, 7, 8, 12, 13, 14, 15, 20", sep = ",") as_seqInterval <- function(x) { old_class <- class(x) class(x) <- c("seqInterval", old_class) x } print.seqInterval <- function(x, ...) { mat <- R.utils::seqToIntervals(x) out <- apply(mat, 1L, \(m) { ifelse(m[1L] == m[2L], m[1L], paste(m, collapse = "-")) }) print(out) } y <- as_seqInterval(x) class(y) #> [1] "seqInterval" "numeric" # autoprinting y y #> [1] "1" "3-5" "7-8" "12-15" "20" # explicit printing y print(y) #> [1] "1" "3-5" "7-8" "12-15" "20" Hope this helps, Rui Barradas -- Este e-mail foi analisado pelo software antiv?rus AVG para verificar a presen?a de v?rus. www.avg.com