Ben - 1 year ago 56

R Question

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 Source

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