Ben Ben - 2 months ago 7
R Question

Convert sequence of integers 1, 2, 3, ... to corresponding sequence of strings A, B, C,

What's a quick, scalable way to convert the integers 1 through N to a corresponding sequence of strings "A", "B", ... "Z", "AA", "AB", ... of the same length?

Alternatively, I'd be happy with something maps the integer vector onto a character vector such that each element of the character vector has the same number of characters. E.g. 1, 2, ... 27 => "AA", "AB", ..., "AZ", "BA"

Example input:

num_vec <- seq(1, 1000)
char_vec <- ???





UPDATE

My hackish, but best working attempt:

library(data.table)
myfunc <- function(n){
if(n <= 26){
dt <- CJ(LETTERS)[, Result := paste0(V1)]
} else if(n <= 26^2){
dt <- CJ(LETTERS, LETTERS)[, Result := paste0(V1, V2)]
} else if(n <= 26^3){
dt <- CJ(LETTERS, LETTERS, LETTERS)[, Result := paste0(V1, V2, V3)]
} else if(n <= 26^4){
dt <- CJ(LETTERS, LETTERS, LETTERS, LETTERS)[, Result := paste0(V1, V2, V3, V4)]
} else if(n <= 26^5){
dt <- CJ(LETTERS, LETTERS, LETTERS, LETTERS, LETTERS)[, Result := paste0(V1, V2, V3, V4, V5)]
} else if(n <= 26^6){
dt <- CJ(LETTERS, LETTERS, LETTERS, LETTERS, LETTERS, LETTERS)[, Result := paste0(V1, V2, V3, V4, V5, V6)]
} else{
stop("n too large")
}

return(dt$Result[1:n])
}

myfunc(10)

Answer

Several nice solutions were posted in the comments already. Only the solution posted by @Gregor here is currently giving the preferred solution by Ben.

However, the methods posted by @eddi, @DavidArenburg and @G.Grothendieck can be adapted to get the prefered outcome as well:

# adaptation of @eddi's method:
library(data.table)
n  <- 29
sz  <- ceiling(log(n)/log(26))
list(LETTERS, c(LETTERS, do.call(CJ, replicate(sz, LETTERS, simplify = F))[, Reduce(paste0, .SD)][1:(n-26)]))[[(n>26)+1]]

# adaptation of @DavidArenburg's method:
n <- 29
list(LETTERS, c(LETTERS, do.call(CJ, replicate((n - 1) %/% 26 + 1, LETTERS, simplify = FALSE))[, do.call(paste0, .SD)][1:(n-26)])[[(n>26)+1]]

# adaptation of @G.Grothendieck's method:
n  <- 29
sz  <- ceiling(log(n)/log(26))
g <- expand.grid(c('',LETTERS), rep(LETTERS, (sz-1)))
g <- g[order(g$Var1),]
do.call(paste0, g)[1:n]

All three result in:

 [1] "A"  "B"  "C"  "D"  "E"  "F"  "G"  "H"  "I"  "J"  "K"  "L"  "M"  "N"  "O" 
[16] "P"  "Q"  "R"  "S"  "T"  "U"  "V"  "W"  "X"  "Y"  "Z"  "AA" "AB" "AC"
Comments