Create a sequence between two letters












28















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 '18 at 8:33











  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.

    – Ronak Shah
    Nov 26 '18 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 '18 at 23:18











  • @Acccumulation correct. I have input as letters and not numbers.

    – Ronak Shah
    Nov 27 '18 at 1:12


















28















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 '18 at 8:33











  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.

    – Ronak Shah
    Nov 26 '18 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 '18 at 23:18











  • @Acccumulation correct. I have input as letters and not numbers.

    – Ronak Shah
    Nov 27 '18 at 1:12
















28












28








28


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 '18 at 8:43









zx8754

29.4k76398




29.4k76398










asked Nov 26 '18 at 8:01









Ronak ShahRonak Shah

35.5k103856




35.5k103856








  • 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 '18 at 8:33











  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.

    – Ronak Shah
    Nov 26 '18 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 '18 at 23:18











  • @Acccumulation correct. I have input as letters and not numbers.

    – Ronak Shah
    Nov 27 '18 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 '18 at 8:33











  • @Spacedman yes, currently looking only for 26 letters from Latin alphabet.

    – Ronak Shah
    Nov 26 '18 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 '18 at 23:18











  • @Acccumulation correct. I have input as letters and not numbers.

    – Ronak Shah
    Nov 27 '18 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 '18 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 '18 at 8:33













@Spacedman yes, currently looking only for 26 letters from Latin alphabet.

– Ronak Shah
Nov 26 '18 at 8:50







@Spacedman yes, currently looking only for 26 letters from Latin alphabet.

– Ronak Shah
Nov 26 '18 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 '18 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 '18 at 23:18













@Acccumulation correct. I have input as letters and not numbers.

– Ronak Shah
Nov 27 '18 at 1:12







@Acccumulation correct. I have input as letters and not numbers.

– Ronak Shah
Nov 27 '18 at 1:12














8 Answers
8






active

oldest

votes


















26














This would be another base R option:



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





share|improve this answer































    17














    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 '18 at 8:11











    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

      – Sven Hohenstein
      Nov 26 '18 at 8:11











    • Definitely better than my use of raw.

      – 42-
      Nov 26 '18 at 8:20



















    12














    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

































      10














      Playing with UTF, something like:



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





      share|improve this answer

































        8














        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


























        • "it does introduce a couple of potentially useful functions" Can you develop?

          – J.Gourlay
          Dec 11 '18 at 14:02






        • 1





          I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

          – 42-
          Dec 11 '18 at 18:20











        • I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

          – J.Gourlay
          Dec 12 '18 at 8:52



















        8














        Why not?



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





        share|improve this answer































          6














          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 '18 at 10:28





















          1














          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',
            autoActivateHeartbeat: false,
            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









            26














            This would be another base R option:



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





            share|improve this answer




























              26














              This would be another base R option:



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





              share|improve this answer


























                26












                26








                26







                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 '18 at 9:08









                r.user.05aprr.user.05apr

                2,0912723




                2,0912723

























                    17














                    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 '18 at 8:11











                    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                      – Sven Hohenstein
                      Nov 26 '18 at 8:11











                    • Definitely better than my use of raw.

                      – 42-
                      Nov 26 '18 at 8:20
















                    17














                    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 '18 at 8:11











                    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                      – Sven Hohenstein
                      Nov 26 '18 at 8:11











                    • Definitely better than my use of raw.

                      – 42-
                      Nov 26 '18 at 8:20














                    17












                    17








                    17







                    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 '18 at 8:10









                    zx8754

                    29.4k76398




                    29.4k76398










                    answered Nov 26 '18 at 8:06









                    Sven HohensteinSven Hohenstein

                    65.4k1298130




                    65.4k1298130













                    • Ow, nice, didn't know about "multiple = TRUE" option.

                      – zx8754
                      Nov 26 '18 at 8:11











                    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                      – Sven Hohenstein
                      Nov 26 '18 at 8:11











                    • Definitely better than my use of raw.

                      – 42-
                      Nov 26 '18 at 8:20



















                    • Ow, nice, didn't know about "multiple = TRUE" option.

                      – zx8754
                      Nov 26 '18 at 8:11











                    • @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                      – Sven Hohenstein
                      Nov 26 '18 at 8:11











                    • Definitely better than my use of raw.

                      – 42-
                      Nov 26 '18 at 8:20

















                    Ow, nice, didn't know about "multiple = TRUE" option.

                    – zx8754
                    Nov 26 '18 at 8:11





                    Ow, nice, didn't know about "multiple = TRUE" option.

                    – zx8754
                    Nov 26 '18 at 8:11













                    @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                    – Sven Hohenstein
                    Nov 26 '18 at 8:11





                    @zx8754 Yes, this parameter makes intToUtf8 a very handy function.

                    – Sven Hohenstein
                    Nov 26 '18 at 8:11













                    Definitely better than my use of raw.

                    – 42-
                    Nov 26 '18 at 8:20





                    Definitely better than my use of raw.

                    – 42-
                    Nov 26 '18 at 8:20











                    12














                    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






























                      12














                      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




























                        12












                        12








                        12







                        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 '18 at 9:15

























                        answered Nov 26 '18 at 8:24









                        JaapJaap

                        55.7k20119132




                        55.7k20119132























                            10














                            Playing with UTF, something like:



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





                            share|improve this answer






























                              10














                              Playing with UTF, something like:



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





                              share|improve this answer




























                                10












                                10








                                10







                                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 '18 at 8:10

























                                answered Nov 26 '18 at 8:05









                                zx8754zx8754

                                29.4k76398




                                29.4k76398























                                    8














                                    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


























                                    • "it does introduce a couple of potentially useful functions" Can you develop?

                                      – J.Gourlay
                                      Dec 11 '18 at 14:02






                                    • 1





                                      I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                      – 42-
                                      Dec 11 '18 at 18:20











                                    • I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                      – J.Gourlay
                                      Dec 12 '18 at 8:52
















                                    8














                                    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


























                                    • "it does introduce a couple of potentially useful functions" Can you develop?

                                      – J.Gourlay
                                      Dec 11 '18 at 14:02






                                    • 1





                                      I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                      – 42-
                                      Dec 11 '18 at 18:20











                                    • I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                      – J.Gourlay
                                      Dec 12 '18 at 8:52














                                    8












                                    8








                                    8







                                    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 '18 at 8:16

























                                    answered Nov 26 '18 at 8:03









                                    42-42-

                                    212k15251398




                                    212k15251398













                                    • "it does introduce a couple of potentially useful functions" Can you develop?

                                      – J.Gourlay
                                      Dec 11 '18 at 14:02






                                    • 1





                                      I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                      – 42-
                                      Dec 11 '18 at 18:20











                                    • I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                      – J.Gourlay
                                      Dec 12 '18 at 8:52



















                                    • "it does introduce a couple of potentially useful functions" Can you develop?

                                      – J.Gourlay
                                      Dec 11 '18 at 14:02






                                    • 1





                                      I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                      – 42-
                                      Dec 11 '18 at 18:20











                                    • I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                      – J.Gourlay
                                      Dec 12 '18 at 8:52

















                                    "it does introduce a couple of potentially useful functions" Can you develop?

                                    – J.Gourlay
                                    Dec 11 '18 at 14:02





                                    "it does introduce a couple of potentially useful functions" Can you develop?

                                    – J.Gourlay
                                    Dec 11 '18 at 14:02




                                    1




                                    1





                                    I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                    – 42-
                                    Dec 11 '18 at 18:20





                                    I often find the process of locating conversion functions like charToRaw and rawToChar difficult. Also in the list of functions I have trouble remembering are: intToUtf8 and chartr, sfsmisc::AsciiToInt, stringi::stri_enc_isascii, stringi::stri_enc_toascii. The last few I located by using ??ascii. I think there are a few other utility functions that I sometimes can locate, but not at this moment cannot. I had a lsit in my .Rprofile file on my "regular" computer but I'm now converting from Mac to Linux and don't have it running.

                                    – 42-
                                    Dec 11 '18 at 18:20













                                    I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                    – J.Gourlay
                                    Dec 12 '18 at 8:52





                                    I see your point, having myself difficulties to remember functions that I've used months ago. Thanks!

                                    – J.Gourlay
                                    Dec 12 '18 at 8:52











                                    8














                                    Why not?



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





                                    share|improve this answer




























                                      8














                                      Why not?



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





                                      share|improve this answer


























                                        8












                                        8








                                        8







                                        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 '18 at 9:55









                                        Anastasiya-Romanova 秀Anastasiya-Romanova 秀

                                        1,9361231




                                        1,9361231























                                            6














                                            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 '18 at 10:28


















                                            6














                                            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 '18 at 10:28
















                                            6












                                            6








                                            6







                                            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 '18 at 8:23









                                            SotosSotos

                                            29k51640




                                            29k51640













                                            • 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 '18 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 '18 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 '18 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 '18 at 10:28













                                            1














                                            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






























                                              1














                                              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




























                                                1












                                                1








                                                1







                                                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 '18 at 10:42

























                                                answered Nov 27 '18 at 10:34









                                                Konrad RudolphKonrad Rudolph

                                                395k1017821025




                                                395k1017821025






























                                                    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.




                                                    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

                                                    Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                                                    ComboBox Display Member on multiple fields

                                                    Is it possible to collect Nectar points via Trainline?