2

I was recently reading a solution to an R4DS exercise. It includes the code:

library(stringr)
replacements <- c("A" = "a", "B" = "b", "C" = "c", "D" = "d", "E" = "e",
                  "F" = "f", "G" = "g", "H" = "h", "I" = "i", "J" = "j", 
                  "K" = "k", "L" = "l", "M" = "m", "N" = "n", "O" = "o", 
                  "P" = "p", "Q" = "q", "R" = "r", "S" = "s", "T" = "t", 
                  "U" = "u", "V" = "v", "W" = "w", "X" = "x", "Y" = "y", 
                  "Z" = "z")
lower_words <- str_replace_all(words, pattern = replacements)
head(lower_words)

and I found the construction of the replacements vector particularly offensive. Nobody should have to do that much typing, particularly given that R has the vectors letters and LETTERS built-in.

Is there any way to automatically construct a vector like this? I tried to create it using expression objects, but I found that we cannot even run code as simple as quote("A" = "a") because "A" = "a" is not a syntactically valid expression. I also tried to create it using strings, e.g. some tricks using paste, but those didn't work because we need the equals sign to not be a string. My nearest guess was substitute(c(a=b), list(a=LETTERS, b=letters)), but the output is obviously incorrect.

J. Mini
  • 1,868
  • 1
  • 9
  • 38
  • 1
    It’s worth checking out `?tolower` and `?toupper` as another way to do these conversions –  Jun 04 '21 at 19:56

3 Answers3

7

with the letters/LETTERS, use

replacements <- setNames(letters, LETTERS)
akrun
  • 874,273
  • 37
  • 540
  • 662
2

Another option but not as efficient as setNames by @akrun

> sapply(LETTERS, gsub, pattern = "(.*)", replacement = "\\L\\1", perl = TRUE)
  A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T
"a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
  U   V   W   X   Y   Z
"u" "v" "w" "x" "y" "z"

or (thank @akrun's comment)

> sapply(letters, tolower)
  a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s   t
"a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
  u   v   w   x   y   z
"u" "v" "w" "x" "y" "z"
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
0

I think this would work as well:

x <- LETTERS; names(x) <- letters

Actually, that is exactly what setNames does.

max
  • 101
  • 2