How can I invert numbers in a vector ONLY if they are consecutive?

So, if the input is a vector such as

v <- (1, 2, 3, 7, 2, 8, 9) 

The output will be

 (3, 2, 1, 7, 2, 9, 8) 

I tried using nested and if loops with a condition as a function is.sorted , but did not succeed.

+5
source share
2 answers

With sample data

 x <- c(1, 2, 3, 7, 2, 8, 9) 

You can divide into "consecutive groups" with

 grp <- cumsum(!c(TRUE, diff(x)==1)) grp # [1] 0 0 0 1 2 3 3 

Basically we look at the diff from the previous item and track changes at any time when this value is not 1.

You can use this group information to reorder these values ​​with ave (this does an in-group conversion).

 revsort<-function(...) sort(...,decreasing=TRUE) ave(x, grp, FUN=revsort) # [1] 3 2 1 7 2 9 8 
+8
source

We could also do:

 x <- c(0, which(diff(vec) != 1), length(vec)) unlist(sapply(seq(length(x) - 1), function(i) rev(vec[(x[i]+1):x[i+1]]))) #[1] 3 2 1 7 2 9 8 

The idea is to first cut a vector based on the positions of consecutive numbers. Then we cross these sections and apply rev .


Data

 vec <- c(1, 2, 3, 7, 2, 8, 9) 

Benchmarking

 library(microbenchmark) vec1 <- c(1, 2, 3, 7, 2, 8, 9) vec2 <- c(1:1000, sample.int(100, 10), 5:500, sample.int(100, 10), 100:125) f_MrFlick <- function(x){ revsort<-function(...) sort(...,decreasing=TRUE) grp <- cumsum(!c(TRUE, diff(x)==1)) ave(x, grp, FUN=revsort) } f_989 <- function(vec){ x <- c(0, which(diff(vec) != 1), length(vec)) unlist(sapply(seq(length(x) - 1), function(i) rev(vec[(x[i]+1):x[i+1]]))) } all(f_MrFlick(vec1)==f_989(vec1)) # [1] TRUE all(f_MrFlick(vec2)==f_989(vec2)) # [1] TRUE length(vec1) # [1] 7 microbenchmark(f_MrFlick(vec1), f_989(vec1)) # Unit: microseconds # expr min lq mean median uq max neval # f_MrFlick(vec1) 287.006 297.0585 305.6340 302.833 312.6695 479.912 100 # f_989(vec1) 113.348 119.7645 124.7901 121.903 127.0360 268.186 100 # -------------------------------------------------------------------------- length(vec2) # [1] 1542 microbenchmark(f_MrFlick(vec2), f_989(vec2)) # Unit: microseconds # expr min lq mean median uq max neval # f_MrFlick(vec2) 1532.553 1565.2745 1725.7540 1627.937 1698.084 3914.149 100 # f_989(vec2) 426.874 454.6765 546.9115 466.439 489.322 2634.383 100 
+5
source

Source: https://habr.com/ru/post/1265979/


All Articles