Create a sequence between two letters











up vote
21
down vote

favorite
1












I want to create a sequence between two letters let's say "b" and "f". So the output is



"b" "c" "d" "e" "f"


For numbers, we can do



2:6 #which gives output as 
[1] 2 3 4 5 6


Is there an easy way to do this with letters as well?



I have gone through Generate a sequence of characters from 'A'-'Z'
but this produces all the letters and not sequence between specific letters.



My current solution is,



indx <- which(letters %in% c("b", "f")); 
letters[indx[1] : indx[2]]

#[1] "b" "c" "d" "e" "f"


This works but I am curious if there is an easy way to do this or a function in any of the package that I have missed?



Note: I do not want letters[2:6] as I do not know 2 and 6 beforehand. It could be between any two letters.










share|improve this question




















  • 2




    What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
    – Spacedman
    Nov 26 at 8:33










  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.
    – Ronak Shah
    Nov 26 at 8:50












  • "I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
    – Acccumulation
    Nov 26 at 23:18










  • @Acccumulation correct. I have input as letters and not numbers.
    – Ronak Shah
    Nov 27 at 1:12

















up vote
21
down vote

favorite
1












I want to create a sequence between two letters let's say "b" and "f". So the output is



"b" "c" "d" "e" "f"


For numbers, we can do



2:6 #which gives output as 
[1] 2 3 4 5 6


Is there an easy way to do this with letters as well?



I have gone through Generate a sequence of characters from 'A'-'Z'
but this produces all the letters and not sequence between specific letters.



My current solution is,



indx <- which(letters %in% c("b", "f")); 
letters[indx[1] : indx[2]]

#[1] "b" "c" "d" "e" "f"


This works but I am curious if there is an easy way to do this or a function in any of the package that I have missed?



Note: I do not want letters[2:6] as I do not know 2 and 6 beforehand. It could be between any two letters.










share|improve this question




















  • 2




    What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
    – Spacedman
    Nov 26 at 8:33










  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.
    – Ronak Shah
    Nov 26 at 8:50












  • "I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
    – Acccumulation
    Nov 26 at 23:18










  • @Acccumulation correct. I have input as letters and not numbers.
    – Ronak Shah
    Nov 27 at 1:12















up vote
21
down vote

favorite
1









up vote
21
down vote

favorite
1






1





I want to create a sequence between two letters let's say "b" and "f". So the output is



"b" "c" "d" "e" "f"


For numbers, we can do



2:6 #which gives output as 
[1] 2 3 4 5 6


Is there an easy way to do this with letters as well?



I have gone through Generate a sequence of characters from 'A'-'Z'
but this produces all the letters and not sequence between specific letters.



My current solution is,



indx <- which(letters %in% c("b", "f")); 
letters[indx[1] : indx[2]]

#[1] "b" "c" "d" "e" "f"


This works but I am curious if there is an easy way to do this or a function in any of the package that I have missed?



Note: I do not want letters[2:6] as I do not know 2 and 6 beforehand. It could be between any two letters.










share|improve this question















I want to create a sequence between two letters let's say "b" and "f". So the output is



"b" "c" "d" "e" "f"


For numbers, we can do



2:6 #which gives output as 
[1] 2 3 4 5 6


Is there an easy way to do this with letters as well?



I have gone through Generate a sequence of characters from 'A'-'Z'
but this produces all the letters and not sequence between specific letters.



My current solution is,



indx <- which(letters %in% c("b", "f")); 
letters[indx[1] : indx[2]]

#[1] "b" "c" "d" "e" "f"


This works but I am curious if there is an easy way to do this or a function in any of the package that I have missed?



Note: I do not want letters[2:6] as I do not know 2 and 6 beforehand. It could be between any two letters.







r character






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 at 8:43









zx8754

28.8k76394




28.8k76394










asked Nov 26 at 8:01









Ronak Shah

28.8k103653




28.8k103653








  • 2




    What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
    – Spacedman
    Nov 26 at 8:33










  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.
    – Ronak Shah
    Nov 26 at 8:50












  • "I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
    – Acccumulation
    Nov 26 at 23:18










  • @Acccumulation correct. I have input as letters and not numbers.
    – Ronak Shah
    Nov 27 at 1:12
















  • 2




    What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
    – Spacedman
    Nov 26 at 8:33










  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.
    – Ronak Shah
    Nov 26 at 8:50












  • "I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
    – Acccumulation
    Nov 26 at 23:18










  • @Acccumulation correct. I have input as letters and not numbers.
    – Ronak Shah
    Nov 27 at 1:12










2




2




What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
– Spacedman
Nov 26 at 8:33




What defines your set of "letters"? Do you want the 26 lower-case letters of the Latin alphabet, or do you want the set of letters in the users current locale? Which could be the french, greek, russian, arabic or other alphabet?
– Spacedman
Nov 26 at 8:33












@Spacedman yes, currently looking only for 26 letters from Latin alphabet.
– Ronak Shah
Nov 26 at 8:50






@Spacedman yes, currently looking only for 26 letters from Latin alphabet.
– Ronak Shah
Nov 26 at 8:50














"I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
– Acccumulation
Nov 26 at 23:18




"I do not want letters[2:6] as I do not know 2 and 6 beforehand." So I take it the reason you don't want to do letters[begin:end] is that you want to generate it based on the limits being given as letters rather than numbers?
– Acccumulation
Nov 26 at 23:18












@Acccumulation correct. I have input as letters and not numbers.
– Ronak Shah
Nov 27 at 1:12






@Acccumulation correct. I have input as letters and not numbers.
– Ronak Shah
Nov 27 at 1:12














8 Answers
8






active

oldest

votes

















up vote
21
down vote



accepted










This would be another base R option:



letters[(letters >= "b") & (letters <= "f")]
# [1] "b" "c" "d" "e" "f"





share|improve this answer




























    up vote
    17
    down vote













    You can create your own function:



    `%:%` <- function(l, r) {
    intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
    }


    Usage:



    "b" %:% "f"
    # [1] "b" "c" "d" "e" "f"

    "f" %:% "b"
    # [1] "f" "e" "d" "c" "b"

    "A" %:% "D"
    # [1] "A" "B" "C" "D"





    share|improve this answer























    • Ow, nice, didn't know about "multiple = TRUE" option.
      – zx8754
      Nov 26 at 8:11










    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
      – Sven Hohenstein
      Nov 26 at 8:11










    • Definitely better than my use of raw.
      – 42-
      Nov 26 at 8:20


















    up vote
    11
    down vote













    Another option with match, seq and do.call:



    letters[do.call(seq, as.list(match(c("b","f"), letters)))]


    which gives:




    [1] "b" "c" "d" "e" "f"





    Making a function of this such that it works with both lower-case and upper-case letters:



    char_seq <- function(lets) {
    switch(all(grepl("[[:upper:]]", lets)) + 1L,
    letters[do.call(seq, as.list(match(lets, letters)))],
    LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
    }


    the output of this:




    > char_seq(c("b","f"))
    [1] "b" "c" "d" "e" "f"

    > char_seq(c("B","F"))
    [1] "B" "C" "D" "E" "F"



    This function can be extended with checks on the correctness of the input:



    char_seq <- function(lets) {
    g <- grepl("[[:upper:]]", lets)
    if(length(g) != 2) stop("Input is not of length 2")
    if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
    switch(all(g) + 1L,
    letters[do.call(seq, as.list(match(lets, letters)))],
    LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
    }


    resulting in proper error-messages when the input is not correct:




    > char_seq(c("B"))
    Error in char_seq(c("B")) : Input is not of length 2

    > char_seq(c("b","F"))
    Error in char_seq(c("b", "F")) :
    Input does not have all lower-case or all upper-case letters






    share|improve this answer






























      up vote
      9
      down vote













      Playing with UTF, something like:



      intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
      # [1] "b" "c" "d" "e" "f"





      share|improve this answer






























        up vote
        8
        down vote













        Perhaps using the raw versions of letters and then converting back to character could be used to define an infix function analogous to ":"



         `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
        seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
        > 'a' %c:% 'g'
        [1] "a" "b" "c" "d" "e" "f" "g"


        I'm certainly not claiming this satisfies the request for "an easy way to do this" and I'm not even certain it would be more efficient, but it does introduce a couple of potentially useful functions.






        share|improve this answer






























          up vote
          8
          down vote













          Why not?



          letters[which(letters == 'b') : which(letters == 'f')]





          share|improve this answer




























            up vote
            6
            down vote













            Iknow it is frowned upon, but here is an eval(parse(...)) solution



            LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
            #[1] "B" "C" "D" "E" "F"





            share|improve this answer





















            • Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
              – Konrad Rudolph
              Nov 27 at 10:28




















            up vote
            1
            down vote













            First things first: your code



            which(letters %in% c("b", "f"))


            Is a valid but convoluted way of writing



            match(c('b', 'f'), letters)


            (Why “convoluted”? Because %in% is a wrapper around match for a specific use-case, which explicitly turns the numeric index into a logical value, i.e. the inverse operation of which.)



            Next, you can of course use the result and convert it into a range via idx[1L] : idx[2L] and there’s nothing wrong with that in this case. But R has an idiomatic way of expressing the concept of calling a function using a vector as its parameters: do.call:



            do.call(`:`, as.list(match(c('b', 'f'), letters)))


            Or, equivalently:



            do.call(seq, as.list(match(c('b', 'f'), letters)))


            {purrr} allows us to do the same without the as.list:



            purrr::invoke(seq, match(c('b', 'f'), letters))


            And, finally, we subset:



            letters[purrr::invoke(seq, match(c('b', 'f'), letters))]





            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53476833%2fcreate-a-sequence-between-two-letters%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              8 Answers
              8






              active

              oldest

              votes








              8 Answers
              8






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              21
              down vote



              accepted










              This would be another base R option:



              letters[(letters >= "b") & (letters <= "f")]
              # [1] "b" "c" "d" "e" "f"





              share|improve this answer

























                up vote
                21
                down vote



                accepted










                This would be another base R option:



                letters[(letters >= "b") & (letters <= "f")]
                # [1] "b" "c" "d" "e" "f"





                share|improve this answer























                  up vote
                  21
                  down vote



                  accepted







                  up vote
                  21
                  down vote



                  accepted






                  This would be another base R option:



                  letters[(letters >= "b") & (letters <= "f")]
                  # [1] "b" "c" "d" "e" "f"





                  share|improve this answer












                  This would be another base R option:



                  letters[(letters >= "b") & (letters <= "f")]
                  # [1] "b" "c" "d" "e" "f"






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 26 at 9:08









                  r.user.05apr

                  1,9921622




                  1,9921622
























                      up vote
                      17
                      down vote













                      You can create your own function:



                      `%:%` <- function(l, r) {
                      intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
                      }


                      Usage:



                      "b" %:% "f"
                      # [1] "b" "c" "d" "e" "f"

                      "f" %:% "b"
                      # [1] "f" "e" "d" "c" "b"

                      "A" %:% "D"
                      # [1] "A" "B" "C" "D"





                      share|improve this answer























                      • Ow, nice, didn't know about "multiple = TRUE" option.
                        – zx8754
                        Nov 26 at 8:11










                      • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                        – Sven Hohenstein
                        Nov 26 at 8:11










                      • Definitely better than my use of raw.
                        – 42-
                        Nov 26 at 8:20















                      up vote
                      17
                      down vote













                      You can create your own function:



                      `%:%` <- function(l, r) {
                      intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
                      }


                      Usage:



                      "b" %:% "f"
                      # [1] "b" "c" "d" "e" "f"

                      "f" %:% "b"
                      # [1] "f" "e" "d" "c" "b"

                      "A" %:% "D"
                      # [1] "A" "B" "C" "D"





                      share|improve this answer























                      • Ow, nice, didn't know about "multiple = TRUE" option.
                        – zx8754
                        Nov 26 at 8:11










                      • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                        – Sven Hohenstein
                        Nov 26 at 8:11










                      • Definitely better than my use of raw.
                        – 42-
                        Nov 26 at 8:20













                      up vote
                      17
                      down vote










                      up vote
                      17
                      down vote









                      You can create your own function:



                      `%:%` <- function(l, r) {
                      intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
                      }


                      Usage:



                      "b" %:% "f"
                      # [1] "b" "c" "d" "e" "f"

                      "f" %:% "b"
                      # [1] "f" "e" "d" "c" "b"

                      "A" %:% "D"
                      # [1] "A" "B" "C" "D"





                      share|improve this answer














                      You can create your own function:



                      `%:%` <- function(l, r) {
                      intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
                      }


                      Usage:



                      "b" %:% "f"
                      # [1] "b" "c" "d" "e" "f"

                      "f" %:% "b"
                      # [1] "f" "e" "d" "c" "b"

                      "A" %:% "D"
                      # [1] "A" "B" "C" "D"






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 26 at 8:10









                      zx8754

                      28.8k76394




                      28.8k76394










                      answered Nov 26 at 8:06









                      Sven Hohenstein

                      64.4k1295127




                      64.4k1295127












                      • Ow, nice, didn't know about "multiple = TRUE" option.
                        – zx8754
                        Nov 26 at 8:11










                      • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                        – Sven Hohenstein
                        Nov 26 at 8:11










                      • Definitely better than my use of raw.
                        – 42-
                        Nov 26 at 8:20


















                      • Ow, nice, didn't know about "multiple = TRUE" option.
                        – zx8754
                        Nov 26 at 8:11










                      • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                        – Sven Hohenstein
                        Nov 26 at 8:11










                      • Definitely better than my use of raw.
                        – 42-
                        Nov 26 at 8:20
















                      Ow, nice, didn't know about "multiple = TRUE" option.
                      – zx8754
                      Nov 26 at 8:11




                      Ow, nice, didn't know about "multiple = TRUE" option.
                      – zx8754
                      Nov 26 at 8:11












                      @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                      – Sven Hohenstein
                      Nov 26 at 8:11




                      @zx8754 Yes, this parameter makes intToUtf8 a very handy function.
                      – Sven Hohenstein
                      Nov 26 at 8:11












                      Definitely better than my use of raw.
                      – 42-
                      Nov 26 at 8:20




                      Definitely better than my use of raw.
                      – 42-
                      Nov 26 at 8:20










                      up vote
                      11
                      down vote













                      Another option with match, seq and do.call:



                      letters[do.call(seq, as.list(match(c("b","f"), letters)))]


                      which gives:




                      [1] "b" "c" "d" "e" "f"





                      Making a function of this such that it works with both lower-case and upper-case letters:



                      char_seq <- function(lets) {
                      switch(all(grepl("[[:upper:]]", lets)) + 1L,
                      letters[do.call(seq, as.list(match(lets, letters)))],
                      LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                      }


                      the output of this:




                      > char_seq(c("b","f"))
                      [1] "b" "c" "d" "e" "f"

                      > char_seq(c("B","F"))
                      [1] "B" "C" "D" "E" "F"



                      This function can be extended with checks on the correctness of the input:



                      char_seq <- function(lets) {
                      g <- grepl("[[:upper:]]", lets)
                      if(length(g) != 2) stop("Input is not of length 2")
                      if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
                      switch(all(g) + 1L,
                      letters[do.call(seq, as.list(match(lets, letters)))],
                      LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                      }


                      resulting in proper error-messages when the input is not correct:




                      > char_seq(c("B"))
                      Error in char_seq(c("B")) : Input is not of length 2

                      > char_seq(c("b","F"))
                      Error in char_seq(c("b", "F")) :
                      Input does not have all lower-case or all upper-case letters






                      share|improve this answer



























                        up vote
                        11
                        down vote













                        Another option with match, seq and do.call:



                        letters[do.call(seq, as.list(match(c("b","f"), letters)))]


                        which gives:




                        [1] "b" "c" "d" "e" "f"





                        Making a function of this such that it works with both lower-case and upper-case letters:



                        char_seq <- function(lets) {
                        switch(all(grepl("[[:upper:]]", lets)) + 1L,
                        letters[do.call(seq, as.list(match(lets, letters)))],
                        LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                        }


                        the output of this:




                        > char_seq(c("b","f"))
                        [1] "b" "c" "d" "e" "f"

                        > char_seq(c("B","F"))
                        [1] "B" "C" "D" "E" "F"



                        This function can be extended with checks on the correctness of the input:



                        char_seq <- function(lets) {
                        g <- grepl("[[:upper:]]", lets)
                        if(length(g) != 2) stop("Input is not of length 2")
                        if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
                        switch(all(g) + 1L,
                        letters[do.call(seq, as.list(match(lets, letters)))],
                        LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                        }


                        resulting in proper error-messages when the input is not correct:




                        > char_seq(c("B"))
                        Error in char_seq(c("B")) : Input is not of length 2

                        > char_seq(c("b","F"))
                        Error in char_seq(c("b", "F")) :
                        Input does not have all lower-case or all upper-case letters






                        share|improve this answer

























                          up vote
                          11
                          down vote










                          up vote
                          11
                          down vote









                          Another option with match, seq and do.call:



                          letters[do.call(seq, as.list(match(c("b","f"), letters)))]


                          which gives:




                          [1] "b" "c" "d" "e" "f"





                          Making a function of this such that it works with both lower-case and upper-case letters:



                          char_seq <- function(lets) {
                          switch(all(grepl("[[:upper:]]", lets)) + 1L,
                          letters[do.call(seq, as.list(match(lets, letters)))],
                          LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                          }


                          the output of this:




                          > char_seq(c("b","f"))
                          [1] "b" "c" "d" "e" "f"

                          > char_seq(c("B","F"))
                          [1] "B" "C" "D" "E" "F"



                          This function can be extended with checks on the correctness of the input:



                          char_seq <- function(lets) {
                          g <- grepl("[[:upper:]]", lets)
                          if(length(g) != 2) stop("Input is not of length 2")
                          if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
                          switch(all(g) + 1L,
                          letters[do.call(seq, as.list(match(lets, letters)))],
                          LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                          }


                          resulting in proper error-messages when the input is not correct:




                          > char_seq(c("B"))
                          Error in char_seq(c("B")) : Input is not of length 2

                          > char_seq(c("b","F"))
                          Error in char_seq(c("b", "F")) :
                          Input does not have all lower-case or all upper-case letters






                          share|improve this answer














                          Another option with match, seq and do.call:



                          letters[do.call(seq, as.list(match(c("b","f"), letters)))]


                          which gives:




                          [1] "b" "c" "d" "e" "f"





                          Making a function of this such that it works with both lower-case and upper-case letters:



                          char_seq <- function(lets) {
                          switch(all(grepl("[[:upper:]]", lets)) + 1L,
                          letters[do.call(seq, as.list(match(lets, letters)))],
                          LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                          }


                          the output of this:




                          > char_seq(c("b","f"))
                          [1] "b" "c" "d" "e" "f"

                          > char_seq(c("B","F"))
                          [1] "B" "C" "D" "E" "F"



                          This function can be extended with checks on the correctness of the input:



                          char_seq <- function(lets) {
                          g <- grepl("[[:upper:]]", lets)
                          if(length(g) != 2) stop("Input is not of length 2")
                          if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
                          switch(all(g) + 1L,
                          letters[do.call(seq, as.list(match(lets, letters)))],
                          LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
                          }


                          resulting in proper error-messages when the input is not correct:




                          > char_seq(c("B"))
                          Error in char_seq(c("B")) : Input is not of length 2

                          > char_seq(c("b","F"))
                          Error in char_seq(c("b", "F")) :
                          Input does not have all lower-case or all upper-case letters







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Nov 26 at 9:15

























                          answered Nov 26 at 8:24









                          Jaap

                          54.3k20116129




                          54.3k20116129






















                              up vote
                              9
                              down vote













                              Playing with UTF, something like:



                              intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
                              # [1] "b" "c" "d" "e" "f"





                              share|improve this answer



























                                up vote
                                9
                                down vote













                                Playing with UTF, something like:



                                intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
                                # [1] "b" "c" "d" "e" "f"





                                share|improve this answer

























                                  up vote
                                  9
                                  down vote










                                  up vote
                                  9
                                  down vote









                                  Playing with UTF, something like:



                                  intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
                                  # [1] "b" "c" "d" "e" "f"





                                  share|improve this answer














                                  Playing with UTF, something like:



                                  intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
                                  # [1] "b" "c" "d" "e" "f"






                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited Nov 26 at 8:10

























                                  answered Nov 26 at 8:05









                                  zx8754

                                  28.8k76394




                                  28.8k76394






















                                      up vote
                                      8
                                      down vote













                                      Perhaps using the raw versions of letters and then converting back to character could be used to define an infix function analogous to ":"



                                       `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
                                      seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
                                      > 'a' %c:% 'g'
                                      [1] "a" "b" "c" "d" "e" "f" "g"


                                      I'm certainly not claiming this satisfies the request for "an easy way to do this" and I'm not even certain it would be more efficient, but it does introduce a couple of potentially useful functions.






                                      share|improve this answer



























                                        up vote
                                        8
                                        down vote













                                        Perhaps using the raw versions of letters and then converting back to character could be used to define an infix function analogous to ":"



                                         `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
                                        seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
                                        > 'a' %c:% 'g'
                                        [1] "a" "b" "c" "d" "e" "f" "g"


                                        I'm certainly not claiming this satisfies the request for "an easy way to do this" and I'm not even certain it would be more efficient, but it does introduce a couple of potentially useful functions.






                                        share|improve this answer

























                                          up vote
                                          8
                                          down vote










                                          up vote
                                          8
                                          down vote









                                          Perhaps using the raw versions of letters and then converting back to character could be used to define an infix function analogous to ":"



                                           `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
                                          seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
                                          > 'a' %c:% 'g'
                                          [1] "a" "b" "c" "d" "e" "f" "g"


                                          I'm certainly not claiming this satisfies the request for "an easy way to do this" and I'm not even certain it would be more efficient, but it does introduce a couple of potentially useful functions.






                                          share|improve this answer














                                          Perhaps using the raw versions of letters and then converting back to character could be used to define an infix function analogous to ":"



                                           `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
                                          seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
                                          > 'a' %c:% 'g'
                                          [1] "a" "b" "c" "d" "e" "f" "g"


                                          I'm certainly not claiming this satisfies the request for "an easy way to do this" and I'm not even certain it would be more efficient, but it does introduce a couple of potentially useful functions.







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited Nov 26 at 8:16

























                                          answered Nov 26 at 8:03









                                          42-

                                          210k14248392




                                          210k14248392






















                                              up vote
                                              8
                                              down vote













                                              Why not?



                                              letters[which(letters == 'b') : which(letters == 'f')]





                                              share|improve this answer

























                                                up vote
                                                8
                                                down vote













                                                Why not?



                                                letters[which(letters == 'b') : which(letters == 'f')]





                                                share|improve this answer























                                                  up vote
                                                  8
                                                  down vote










                                                  up vote
                                                  8
                                                  down vote









                                                  Why not?



                                                  letters[which(letters == 'b') : which(letters == 'f')]





                                                  share|improve this answer












                                                  Why not?



                                                  letters[which(letters == 'b') : which(letters == 'f')]






                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered Nov 26 at 9:55









                                                  Anastasiya-Romanova 秀

                                                  1,9211230




                                                  1,9211230






















                                                      up vote
                                                      6
                                                      down vote













                                                      Iknow it is frowned upon, but here is an eval(parse(...)) solution



                                                      LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
                                                      #[1] "B" "C" "D" "E" "F"





                                                      share|improve this answer





















                                                      • Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                        – Konrad Rudolph
                                                        Nov 27 at 10:28

















                                                      up vote
                                                      6
                                                      down vote













                                                      Iknow it is frowned upon, but here is an eval(parse(...)) solution



                                                      LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
                                                      #[1] "B" "C" "D" "E" "F"





                                                      share|improve this answer





















                                                      • Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                        – Konrad Rudolph
                                                        Nov 27 at 10:28















                                                      up vote
                                                      6
                                                      down vote










                                                      up vote
                                                      6
                                                      down vote









                                                      Iknow it is frowned upon, but here is an eval(parse(...)) solution



                                                      LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
                                                      #[1] "B" "C" "D" "E" "F"





                                                      share|improve this answer












                                                      Iknow it is frowned upon, but here is an eval(parse(...)) solution



                                                      LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
                                                      #[1] "B" "C" "D" "E" "F"






                                                      share|improve this answer












                                                      share|improve this answer



                                                      share|improve this answer










                                                      answered Nov 26 at 8:23









                                                      Sotos

                                                      27.1k51540




                                                      27.1k51540












                                                      • Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                        – Konrad Rudolph
                                                        Nov 27 at 10:28




















                                                      • Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                        – Konrad Rudolph
                                                        Nov 27 at 10:28


















                                                      Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                      – Konrad Rudolph
                                                      Nov 27 at 10:28






                                                      Using eval and parse here is blatant abuse, sorry. You can implement the same logic without (e.g. with do.call), although the logic itself is also needlessly convoluted.
                                                      – Konrad Rudolph
                                                      Nov 27 at 10:28












                                                      up vote
                                                      1
                                                      down vote













                                                      First things first: your code



                                                      which(letters %in% c("b", "f"))


                                                      Is a valid but convoluted way of writing



                                                      match(c('b', 'f'), letters)


                                                      (Why “convoluted”? Because %in% is a wrapper around match for a specific use-case, which explicitly turns the numeric index into a logical value, i.e. the inverse operation of which.)



                                                      Next, you can of course use the result and convert it into a range via idx[1L] : idx[2L] and there’s nothing wrong with that in this case. But R has an idiomatic way of expressing the concept of calling a function using a vector as its parameters: do.call:



                                                      do.call(`:`, as.list(match(c('b', 'f'), letters)))


                                                      Or, equivalently:



                                                      do.call(seq, as.list(match(c('b', 'f'), letters)))


                                                      {purrr} allows us to do the same without the as.list:



                                                      purrr::invoke(seq, match(c('b', 'f'), letters))


                                                      And, finally, we subset:



                                                      letters[purrr::invoke(seq, match(c('b', 'f'), letters))]





                                                      share|improve this answer



























                                                        up vote
                                                        1
                                                        down vote













                                                        First things first: your code



                                                        which(letters %in% c("b", "f"))


                                                        Is a valid but convoluted way of writing



                                                        match(c('b', 'f'), letters)


                                                        (Why “convoluted”? Because %in% is a wrapper around match for a specific use-case, which explicitly turns the numeric index into a logical value, i.e. the inverse operation of which.)



                                                        Next, you can of course use the result and convert it into a range via idx[1L] : idx[2L] and there’s nothing wrong with that in this case. But R has an idiomatic way of expressing the concept of calling a function using a vector as its parameters: do.call:



                                                        do.call(`:`, as.list(match(c('b', 'f'), letters)))


                                                        Or, equivalently:



                                                        do.call(seq, as.list(match(c('b', 'f'), letters)))


                                                        {purrr} allows us to do the same without the as.list:



                                                        purrr::invoke(seq, match(c('b', 'f'), letters))


                                                        And, finally, we subset:



                                                        letters[purrr::invoke(seq, match(c('b', 'f'), letters))]





                                                        share|improve this answer

























                                                          up vote
                                                          1
                                                          down vote










                                                          up vote
                                                          1
                                                          down vote









                                                          First things first: your code



                                                          which(letters %in% c("b", "f"))


                                                          Is a valid but convoluted way of writing



                                                          match(c('b', 'f'), letters)


                                                          (Why “convoluted”? Because %in% is a wrapper around match for a specific use-case, which explicitly turns the numeric index into a logical value, i.e. the inverse operation of which.)



                                                          Next, you can of course use the result and convert it into a range via idx[1L] : idx[2L] and there’s nothing wrong with that in this case. But R has an idiomatic way of expressing the concept of calling a function using a vector as its parameters: do.call:



                                                          do.call(`:`, as.list(match(c('b', 'f'), letters)))


                                                          Or, equivalently:



                                                          do.call(seq, as.list(match(c('b', 'f'), letters)))


                                                          {purrr} allows us to do the same without the as.list:



                                                          purrr::invoke(seq, match(c('b', 'f'), letters))


                                                          And, finally, we subset:



                                                          letters[purrr::invoke(seq, match(c('b', 'f'), letters))]





                                                          share|improve this answer














                                                          First things first: your code



                                                          which(letters %in% c("b", "f"))


                                                          Is a valid but convoluted way of writing



                                                          match(c('b', 'f'), letters)


                                                          (Why “convoluted”? Because %in% is a wrapper around match for a specific use-case, which explicitly turns the numeric index into a logical value, i.e. the inverse operation of which.)



                                                          Next, you can of course use the result and convert it into a range via idx[1L] : idx[2L] and there’s nothing wrong with that in this case. But R has an idiomatic way of expressing the concept of calling a function using a vector as its parameters: do.call:



                                                          do.call(`:`, as.list(match(c('b', 'f'), letters)))


                                                          Or, equivalently:



                                                          do.call(seq, as.list(match(c('b', 'f'), letters)))


                                                          {purrr} allows us to do the same without the as.list:



                                                          purrr::invoke(seq, match(c('b', 'f'), letters))


                                                          And, finally, we subset:



                                                          letters[purrr::invoke(seq, match(c('b', 'f'), letters))]






                                                          share|improve this answer














                                                          share|improve this answer



                                                          share|improve this answer








                                                          edited Nov 27 at 10:42

























                                                          answered Nov 27 at 10:34









                                                          Konrad Rudolph

                                                          392k1017721021




                                                          392k1017721021






























                                                              draft saved

                                                              draft discarded




















































                                                              Thanks for contributing an answer to Stack Overflow!


                                                              • Please be sure to answer the question. Provide details and share your research!

                                                              But avoid



                                                              • Asking for help, clarification, or responding to other answers.

                                                              • Making statements based on opinion; back them up with references or personal experience.


                                                              To learn more, see our tips on writing great answers.





                                                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                              Please pay close attention to the following guidance:


                                                              • Please be sure to answer the question. Provide details and share your research!

                                                              But avoid



                                                              • Asking for help, clarification, or responding to other answers.

                                                              • Making statements based on opinion; back them up with references or personal experience.


                                                              To learn more, see our tips on writing great answers.




                                                              draft saved


                                                              draft discarded














                                                              StackExchange.ready(
                                                              function () {
                                                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53476833%2fcreate-a-sequence-between-two-letters%23new-answer', 'question_page');
                                                              }
                                                              );

                                                              Post as a guest















                                                              Required, but never shown





















































                                                              Required, but never shown














                                                              Required, but never shown












                                                              Required, but never shown







                                                              Required, but never shown

































                                                              Required, but never shown














                                                              Required, but never shown












                                                              Required, but never shown







                                                              Required, but never shown







                                                              Popular posts from this blog

                                                              AnyDesk - Fatal Program Failure

                                                              How to calibrate 16:9 built-in touch-screen to a 4:3 resolution?

                                                              QoS: MAC-Priority for clients behind a repeater