简体   繁体   中英

R matching letters and numbers with a For Loop

I am trying to print a matching letter and number on every line. However, the code repeats itself 26 x 26 times instead of 26 x 1 time. I hoped the break after reaching the first "z" would stop the loop but it doesn't.

for (i in 1:26) {
  l = letters
  num = sapply(1:26, toOrdinal)
  print(paste0(l," is the ",num," letter of the alphabet."))
  if (l == "z") {
    break
  }
}

I wrote an alternate piece of code that puts the data in a matrix to control the print, but I would like to make the top piece work for my own edification.

#Create Data Matrix contain desired data to restrict continuous printing
matrix.letters <- matrix(nrow = 26, ncol = 3, dimnames = list(NULL, c("num", "letter", "ordinal")))
matrix.letters[,'num'] <- 1:26
matrix.letters[, 'ordinal'] <- sapply(1:26, toOrdinal)
matrix.letters[,'letter'] <- letters

#create index observation
letters.df <- as.data.frame(matrix.letters)

#YES - correct print achieved
for (i in nrow(letters.df)) {
  print(paste0(letters.df$letter," is the ",letters.df$ordinal, " letter of the alphabet."))
}

First, please be clear about non-base packages. I'm inferring the `toOrdinal::toOrdinal function in your question.

Up front, your issue is that you are looping, but you should be indexing using that loop count within multiple places in your code:

for (i in 1:26) {
  l = letters[i]
  num = toOrdinal(i)
  print(paste0(l," is the ",num," letter of the alphabet."))
  if (l == "z") {
    break
  }
}
# [1] "a is the 1st letter of the alphabet."
# [1] "b is the 2nd letter of the alphabet."
# [1] "c is the 3rd letter of the alphabet."
# [1] "d is the 4th letter of the alphabet."
# [1] "e is the 5th letter of the alphabet."
# [1] "f is the 6th letter of the alphabet."
# [1] "g is the 7th letter of the alphabet."
# [1] "h is the 8th letter of the alphabet."
# [1] "i is the 9th letter of the alphabet."
# [1] "j is the 10th letter of the alphabet."
# [1] "k is the 11th letter of the alphabet."
# [1] "l is the 12th letter of the alphabet."
# [1] "m is the 13th letter of the alphabet."
# [1] "n is the 14th letter of the alphabet."
# [1] "o is the 15th letter of the alphabet."
# [1] "p is the 16th letter of the alphabet."
# [1] "q is the 17th letter of the alphabet."
# [1] "r is the 18th letter of the alphabet."
# [1] "s is the 19th letter of the alphabet."
# [1] "t is the 20th letter of the alphabet."
# [1] "u is the 21st letter of the alphabet."
# [1] "v is the 22nd letter of the alphabet."
# [1] "w is the 23rd letter of the alphabet."
# [1] "x is the 24th letter of the alphabet."
# [1] "y is the 25th letter of the alphabet."
# [1] "z is the 26th letter of the alphabet."

As @Joe said in the comment, in your original code, paste0 is getting l (length 26) and num (length 26), and therefore it is returning a vector (length 26) that is being printed. My first thought on your for loop was inefficient reassignments, since l = letters was doing exactly the same thing each pass, same with num = sapply(..) , so those could have been moved outside the loop. In fact, that can happen, with slightly different code:

Ls <- letters
nums <- sapply(1:26, toOrdinal)
for (i in 1:26) {
  print(paste0(Ls[i]," is the ",nums[i]," letter of the alphabet."))
  if (Ls[i] == "z") {
    break
  }
}

And one last bit of "unnecessary" code there: break is useful when you expect that the for (or while or repeat or...) code will go on too long. In this case, we know that Ls[i] == "z" happens on the 26th time in the loop, and it will be stopping on its own accord regardless. So for this loop, the break portion is unnecessary. (If this is just an exercise for flow-control, then it's a good lesson to know.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM