Alphabetic comparison of two strings












12














I tried to compare two strings (alphabetically), but I found some problems using the pdfstrcmp command: 1- because it needs pdftex; 2- because it is case sensitive.



The first problem is not so relevant, because I can use another compiler.



However the second problem is complicated to me. In pdfstrcmd command all lowercase chars in comparison with an uppercase char has the same answer.



So I tried to use the comparison of chars using ifnumuccode#1uccode#2 (...), but the reply was "! Improper alphabetic constant"



Is there anyone who knows a solution to this problem?



My code:



documentclass{article}

newcounter{auxCountGetCharAt}

makeatletter

deffuncGetCharAt#1#2relax{stepcounter{auxCountGetCharAt}edef@tempb{thevalue{auxCountGetCharAt}}ifx@tempa@tempb#1else{ifxrelax#2relaxelsefuncGetCharAt#2relaxfi}fi}

defgetCharAt#1#2{%
edef@tempa{#2}%
setcounter{auxCountGetCharAt}{0}%
funcGetCharAt#1relax%
}

newcommandcompareChars[2]{ifnumuccode`#1>uccode`#2 1else{ifnumuccode`#1=uccode`#2 0else -1fi}fi}

newcommandcompareStrings[2]{%
def@tempc{getCharAt{#1}{1}}%
def@tempd{getCharAt{#2}{1}}%
compareChars{@tempc}{@tempd}%
}

begin{document}

compareStrings{abcdefg}{bcdefg}

compareStrings{Abcdefg}{bcdefg}

compareStrings{Bbcdefg}{acdefg}

compareStrings{bbcdefg}{acdefg}

compareStrings{bcdefg}{bcdeag}

end{document}









share|improve this question





























    12














    I tried to compare two strings (alphabetically), but I found some problems using the pdfstrcmp command: 1- because it needs pdftex; 2- because it is case sensitive.



    The first problem is not so relevant, because I can use another compiler.



    However the second problem is complicated to me. In pdfstrcmd command all lowercase chars in comparison with an uppercase char has the same answer.



    So I tried to use the comparison of chars using ifnumuccode#1uccode#2 (...), but the reply was "! Improper alphabetic constant"



    Is there anyone who knows a solution to this problem?



    My code:



    documentclass{article}

    newcounter{auxCountGetCharAt}

    makeatletter

    deffuncGetCharAt#1#2relax{stepcounter{auxCountGetCharAt}edef@tempb{thevalue{auxCountGetCharAt}}ifx@tempa@tempb#1else{ifxrelax#2relaxelsefuncGetCharAt#2relaxfi}fi}

    defgetCharAt#1#2{%
    edef@tempa{#2}%
    setcounter{auxCountGetCharAt}{0}%
    funcGetCharAt#1relax%
    }

    newcommandcompareChars[2]{ifnumuccode`#1>uccode`#2 1else{ifnumuccode`#1=uccode`#2 0else -1fi}fi}

    newcommandcompareStrings[2]{%
    def@tempc{getCharAt{#1}{1}}%
    def@tempd{getCharAt{#2}{1}}%
    compareChars{@tempc}{@tempd}%
    }

    begin{document}

    compareStrings{abcdefg}{bcdefg}

    compareStrings{Abcdefg}{bcdefg}

    compareStrings{Bbcdefg}{acdefg}

    compareStrings{bbcdefg}{acdefg}

    compareStrings{bcdefg}{bcdeag}

    end{document}









    share|improve this question



























      12












      12








      12


      1





      I tried to compare two strings (alphabetically), but I found some problems using the pdfstrcmp command: 1- because it needs pdftex; 2- because it is case sensitive.



      The first problem is not so relevant, because I can use another compiler.



      However the second problem is complicated to me. In pdfstrcmd command all lowercase chars in comparison with an uppercase char has the same answer.



      So I tried to use the comparison of chars using ifnumuccode#1uccode#2 (...), but the reply was "! Improper alphabetic constant"



      Is there anyone who knows a solution to this problem?



      My code:



      documentclass{article}

      newcounter{auxCountGetCharAt}

      makeatletter

      deffuncGetCharAt#1#2relax{stepcounter{auxCountGetCharAt}edef@tempb{thevalue{auxCountGetCharAt}}ifx@tempa@tempb#1else{ifxrelax#2relaxelsefuncGetCharAt#2relaxfi}fi}

      defgetCharAt#1#2{%
      edef@tempa{#2}%
      setcounter{auxCountGetCharAt}{0}%
      funcGetCharAt#1relax%
      }

      newcommandcompareChars[2]{ifnumuccode`#1>uccode`#2 1else{ifnumuccode`#1=uccode`#2 0else -1fi}fi}

      newcommandcompareStrings[2]{%
      def@tempc{getCharAt{#1}{1}}%
      def@tempd{getCharAt{#2}{1}}%
      compareChars{@tempc}{@tempd}%
      }

      begin{document}

      compareStrings{abcdefg}{bcdefg}

      compareStrings{Abcdefg}{bcdefg}

      compareStrings{Bbcdefg}{acdefg}

      compareStrings{bbcdefg}{acdefg}

      compareStrings{bcdefg}{bcdeag}

      end{document}









      share|improve this question















      I tried to compare two strings (alphabetically), but I found some problems using the pdfstrcmp command: 1- because it needs pdftex; 2- because it is case sensitive.



      The first problem is not so relevant, because I can use another compiler.



      However the second problem is complicated to me. In pdfstrcmd command all lowercase chars in comparison with an uppercase char has the same answer.



      So I tried to use the comparison of chars using ifnumuccode#1uccode#2 (...), but the reply was "! Improper alphabetic constant"



      Is there anyone who knows a solution to this problem?



      My code:



      documentclass{article}

      newcounter{auxCountGetCharAt}

      makeatletter

      deffuncGetCharAt#1#2relax{stepcounter{auxCountGetCharAt}edef@tempb{thevalue{auxCountGetCharAt}}ifx@tempa@tempb#1else{ifxrelax#2relaxelsefuncGetCharAt#2relaxfi}fi}

      defgetCharAt#1#2{%
      edef@tempa{#2}%
      setcounter{auxCountGetCharAt}{0}%
      funcGetCharAt#1relax%
      }

      newcommandcompareChars[2]{ifnumuccode`#1>uccode`#2 1else{ifnumuccode`#1=uccode`#2 0else -1fi}fi}

      newcommandcompareStrings[2]{%
      def@tempc{getCharAt{#1}{1}}%
      def@tempd{getCharAt{#2}{1}}%
      compareChars{@tempc}{@tempd}%
      }

      begin{document}

      compareStrings{abcdefg}{bcdefg}

      compareStrings{Abcdefg}{bcdefg}

      compareStrings{Bbcdefg}{acdefg}

      compareStrings{bbcdefg}{acdefg}

      compareStrings{bcdefg}{bcdeag}

      end{document}






      strings comparison






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 30 '12 at 15:41









      Claudio Fiandrino

      52.1k11152306




      52.1k11152306










      asked May 30 '12 at 15:37









      Caio

      17718




      17718






















          2 Answers
          2






          active

          oldest

          votes


















          11














          If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:



          documentclass{article}
          usepackage{pdftexcmds}

          makeatletter
          defcompareStrings#1#2{%
          lowercase{edef@tempa{pdf@strcmp{#1}{#2}}}%
          typeout{#1 -- #2: @tempa}%
          }
          makeatother

          compareStrings{abcdefg}{bcdefg}

          compareStrings{Abcdefg}{bcdefg}

          compareStrings{Bbcdefg}{acdefg}

          compareStrings{bbcdefg}{acdefg}

          compareStrings{bcdefg}{bcdeag}

          compareStrings{ABcDeF}{aBCdef}


          The pdftexcmds package defines pdf@strcmp to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result is



          abcdefg -- bcdefg: -1
          Abcdefg -- bcdefg: -1
          Bbcdefg -- acdefg: 1
          bbcdefg -- acdefg: 1
          bcdefg -- bcdeag: 1
          ABcDeF -- aBCdef: 0


          The edef allows also to pass macros to compareStrings, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).



          If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:



          makeatletter
          newcommandcompareStringsDo[5]{%
          lowercase{ifcasepdf@strcmp{#1}{#2}}%
          #4or
          #5else
          #3fi
          }
          makeatother


          So with compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>} the <before> code will be executed when <str1> comes before <str2> in the alphabetical order, <equal> if they are the same and <after> otherwise (after normalization to lowercase).



          An expl3 version that has the big advantage of being fully expandable.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewExpandableDocumentCommand{compareStrings}{mm}
          {
          str_if_eq:eeTF { str_lower_case:f { #1 } } { str_lower_case:f { #2 } }
          { equalStrings{#1}{#2} }
          { differentStrings{#1}{#2} }
          }
          ExplSyntaxOff

          newcommand{equalStrings}[2]{typeout{Strings #1 and #2 are equal}}
          newcommand{differentStrings}[2]{typeout{Strings #1 and #2 are different}}

          newcommand{test}{AbCdEF}

          compareStrings{abcdefg}{bcdefg}

          compareStrings{Abcdefg}{bcdefg}

          compareStrings{Bbcdefg}{acdefg}

          compareStrings{bbcdefg}{acdefg}

          compareStrings{bcdefg}{bcdeag}

          compareStrings{ABcDeF}{aBCdef}

          compareStrings{ABcDeF}{test}

          stop


          The console output:



          Strings abcdefg and bcdefg are different
          Strings Abcdefg and bcdefg are different
          Strings Bbcdefg and acdefg are different
          Strings bbcdefg and acdefg are different
          Strings bcdefg and bcdeag are different
          Strings ABcDeF and aBCdef are equal
          Strings ABcDeF and AbCdEF are equal





          share|improve this answer































            9














            Old, simple, not-really-the-answer-kind-of-answer



            [kept for 'historical purposes' - can be deleted anytime]



            I'm no big LaTeX wizard as egreg for instance. :) So I propose a much simpler solution, to simply use a package out there: xstring:



            documentclass{article}

            usepackage{xstring}

            begin{document}

            IfStrEq{abcdefg}{bcdefg}{true}{false}
            IfStrEq{Abcdefg}{bcdefg}{true}{false}
            IfStrEq{Bbcdefg}{acdefg}{true}{false}
            IfStrEq{bbcdefg}{acdefg}{true}{false}
            IfStrEq{bcdefg}{bcdeag}{true}{false}
            IfStrEq{bcdeag}{bcdeag}{true}{false}

            end{document}


            The command is really simple to use: it takes 4 arguments, the first two are the strings to be compared, the 3rd is to be executed when the comparison result is true, otherwise argument number 4 will be executed.



            The package provides a lot more functions for fancy string manipulations.





            EDIT: New, corrected answer (still using xstring)



            After posting my first answer, I was told (rightfully!) that the question was about more than just a simple equality check. Rather it is about comparing whether a string comes before or after another one alphabetically. After scratching my head a bit, I came up with this:



            documentclass{article}

            usepackage{xstring}
            usepackage[nomessages]{fp}

            newcommand{compAlph}[2]{%

            StrCompare{#1}{#2}[posdiff]

            Difference between input strings detected at position:

            posdiffsmallskip

            StrChar{#1}{posdiff}[myfirstchar]

            Character in the 1st string that is different:

            myfirstcharsmallskip

            StrChar{#2}{posdiff}[mysecondchar]

            Character in the 2nd string that is different:

            mysecondcharsmallskip

            StrPosition{abcdefghijklmnopqrstuvwxyz}{myfirstchar}[posfirst]
            StrPosition{abcdefghijklmnopqrstuvwxyz}{mysecondchar}[possecond]

            FPeval{posrel}{clip(possecond-posfirst)}
            `Relative distance' between characters:

            posrel
            }

            begin{document}

            compAlph{zyzzyzzyryx}{bcdeag}
            bigskip
            compAlph{abcdefg}{bcdefg}
            bigskip
            compAlph{bbcdefg}{acdefg}
            bigskip
            compAlph{bbcdefg}{acdefg}
            bigskip
            compAlph{bcdefg}{bcdeag}
            bigskip
            compAlph{bcdeag}{bcdeag}

            end{document}


            The 'relative distance' thing shows actually, 'how far apart' in the defined alphabet the characters are that differ. If the value is negative, the second word would need to move 'up', before the other word to have them in alphabetical order, and the other way around if it is positive.



            It is not as elegant as egreg's solution and prints the result into the document, it also might seem a bit crude and may need a bit of tuning, but it's an alternative. :)






            share|improve this answer























            • The OP, however, needs not to check for equality, but for alphabetic order.
              – Daniel
              May 30 '12 at 16:34










            • @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
              – Count Zero
              May 30 '12 at 17:17










            • Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
              – Count Zero
              May 31 '12 at 11:04











            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "85"
            };
            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: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            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%2ftex.stackexchange.com%2fquestions%2f57887%2falphabetic-comparison-of-two-strings%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            11














            If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:



            documentclass{article}
            usepackage{pdftexcmds}

            makeatletter
            defcompareStrings#1#2{%
            lowercase{edef@tempa{pdf@strcmp{#1}{#2}}}%
            typeout{#1 -- #2: @tempa}%
            }
            makeatother

            compareStrings{abcdefg}{bcdefg}

            compareStrings{Abcdefg}{bcdefg}

            compareStrings{Bbcdefg}{acdefg}

            compareStrings{bbcdefg}{acdefg}

            compareStrings{bcdefg}{bcdeag}

            compareStrings{ABcDeF}{aBCdef}


            The pdftexcmds package defines pdf@strcmp to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result is



            abcdefg -- bcdefg: -1
            Abcdefg -- bcdefg: -1
            Bbcdefg -- acdefg: 1
            bbcdefg -- acdefg: 1
            bcdefg -- bcdeag: 1
            ABcDeF -- aBCdef: 0


            The edef allows also to pass macros to compareStrings, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).



            If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:



            makeatletter
            newcommandcompareStringsDo[5]{%
            lowercase{ifcasepdf@strcmp{#1}{#2}}%
            #4or
            #5else
            #3fi
            }
            makeatother


            So with compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>} the <before> code will be executed when <str1> comes before <str2> in the alphabetical order, <equal> if they are the same and <after> otherwise (after normalization to lowercase).



            An expl3 version that has the big advantage of being fully expandable.



            documentclass{article}
            usepackage{xparse}

            ExplSyntaxOn
            NewExpandableDocumentCommand{compareStrings}{mm}
            {
            str_if_eq:eeTF { str_lower_case:f { #1 } } { str_lower_case:f { #2 } }
            { equalStrings{#1}{#2} }
            { differentStrings{#1}{#2} }
            }
            ExplSyntaxOff

            newcommand{equalStrings}[2]{typeout{Strings #1 and #2 are equal}}
            newcommand{differentStrings}[2]{typeout{Strings #1 and #2 are different}}

            newcommand{test}{AbCdEF}

            compareStrings{abcdefg}{bcdefg}

            compareStrings{Abcdefg}{bcdefg}

            compareStrings{Bbcdefg}{acdefg}

            compareStrings{bbcdefg}{acdefg}

            compareStrings{bcdefg}{bcdeag}

            compareStrings{ABcDeF}{aBCdef}

            compareStrings{ABcDeF}{test}

            stop


            The console output:



            Strings abcdefg and bcdefg are different
            Strings Abcdefg and bcdefg are different
            Strings Bbcdefg and acdefg are different
            Strings bbcdefg and acdefg are different
            Strings bcdefg and bcdeag are different
            Strings ABcDeF and aBCdef are equal
            Strings ABcDeF and AbCdEF are equal





            share|improve this answer




























              11














              If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:



              documentclass{article}
              usepackage{pdftexcmds}

              makeatletter
              defcompareStrings#1#2{%
              lowercase{edef@tempa{pdf@strcmp{#1}{#2}}}%
              typeout{#1 -- #2: @tempa}%
              }
              makeatother

              compareStrings{abcdefg}{bcdefg}

              compareStrings{Abcdefg}{bcdefg}

              compareStrings{Bbcdefg}{acdefg}

              compareStrings{bbcdefg}{acdefg}

              compareStrings{bcdefg}{bcdeag}

              compareStrings{ABcDeF}{aBCdef}


              The pdftexcmds package defines pdf@strcmp to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result is



              abcdefg -- bcdefg: -1
              Abcdefg -- bcdefg: -1
              Bbcdefg -- acdefg: 1
              bbcdefg -- acdefg: 1
              bcdefg -- bcdeag: 1
              ABcDeF -- aBCdef: 0


              The edef allows also to pass macros to compareStrings, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).



              If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:



              makeatletter
              newcommandcompareStringsDo[5]{%
              lowercase{ifcasepdf@strcmp{#1}{#2}}%
              #4or
              #5else
              #3fi
              }
              makeatother


              So with compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>} the <before> code will be executed when <str1> comes before <str2> in the alphabetical order, <equal> if they are the same and <after> otherwise (after normalization to lowercase).



              An expl3 version that has the big advantage of being fully expandable.



              documentclass{article}
              usepackage{xparse}

              ExplSyntaxOn
              NewExpandableDocumentCommand{compareStrings}{mm}
              {
              str_if_eq:eeTF { str_lower_case:f { #1 } } { str_lower_case:f { #2 } }
              { equalStrings{#1}{#2} }
              { differentStrings{#1}{#2} }
              }
              ExplSyntaxOff

              newcommand{equalStrings}[2]{typeout{Strings #1 and #2 are equal}}
              newcommand{differentStrings}[2]{typeout{Strings #1 and #2 are different}}

              newcommand{test}{AbCdEF}

              compareStrings{abcdefg}{bcdefg}

              compareStrings{Abcdefg}{bcdefg}

              compareStrings{Bbcdefg}{acdefg}

              compareStrings{bbcdefg}{acdefg}

              compareStrings{bcdefg}{bcdeag}

              compareStrings{ABcDeF}{aBCdef}

              compareStrings{ABcDeF}{test}

              stop


              The console output:



              Strings abcdefg and bcdefg are different
              Strings Abcdefg and bcdefg are different
              Strings Bbcdefg and acdefg are different
              Strings bbcdefg and acdefg are different
              Strings bcdefg and bcdeag are different
              Strings ABcDeF and aBCdef are equal
              Strings ABcDeF and AbCdEF are equal





              share|improve this answer


























                11












                11








                11






                If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:



                documentclass{article}
                usepackage{pdftexcmds}

                makeatletter
                defcompareStrings#1#2{%
                lowercase{edef@tempa{pdf@strcmp{#1}{#2}}}%
                typeout{#1 -- #2: @tempa}%
                }
                makeatother

                compareStrings{abcdefg}{bcdefg}

                compareStrings{Abcdefg}{bcdefg}

                compareStrings{Bbcdefg}{acdefg}

                compareStrings{bbcdefg}{acdefg}

                compareStrings{bcdefg}{bcdeag}

                compareStrings{ABcDeF}{aBCdef}


                The pdftexcmds package defines pdf@strcmp to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result is



                abcdefg -- bcdefg: -1
                Abcdefg -- bcdefg: -1
                Bbcdefg -- acdefg: 1
                bbcdefg -- acdefg: 1
                bcdefg -- bcdeag: 1
                ABcDeF -- aBCdef: 0


                The edef allows also to pass macros to compareStrings, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).



                If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:



                makeatletter
                newcommandcompareStringsDo[5]{%
                lowercase{ifcasepdf@strcmp{#1}{#2}}%
                #4or
                #5else
                #3fi
                }
                makeatother


                So with compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>} the <before> code will be executed when <str1> comes before <str2> in the alphabetical order, <equal> if they are the same and <after> otherwise (after normalization to lowercase).



                An expl3 version that has the big advantage of being fully expandable.



                documentclass{article}
                usepackage{xparse}

                ExplSyntaxOn
                NewExpandableDocumentCommand{compareStrings}{mm}
                {
                str_if_eq:eeTF { str_lower_case:f { #1 } } { str_lower_case:f { #2 } }
                { equalStrings{#1}{#2} }
                { differentStrings{#1}{#2} }
                }
                ExplSyntaxOff

                newcommand{equalStrings}[2]{typeout{Strings #1 and #2 are equal}}
                newcommand{differentStrings}[2]{typeout{Strings #1 and #2 are different}}

                newcommand{test}{AbCdEF}

                compareStrings{abcdefg}{bcdefg}

                compareStrings{Abcdefg}{bcdefg}

                compareStrings{Bbcdefg}{acdefg}

                compareStrings{bbcdefg}{acdefg}

                compareStrings{bcdefg}{bcdeag}

                compareStrings{ABcDeF}{aBCdef}

                compareStrings{ABcDeF}{test}

                stop


                The console output:



                Strings abcdefg and bcdefg are different
                Strings Abcdefg and bcdefg are different
                Strings Bbcdefg and acdefg are different
                Strings bbcdefg and acdefg are different
                Strings bcdefg and bcdeag are different
                Strings ABcDeF and aBCdef are equal
                Strings ABcDeF and AbCdEF are equal





                share|improve this answer














                If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:



                documentclass{article}
                usepackage{pdftexcmds}

                makeatletter
                defcompareStrings#1#2{%
                lowercase{edef@tempa{pdf@strcmp{#1}{#2}}}%
                typeout{#1 -- #2: @tempa}%
                }
                makeatother

                compareStrings{abcdefg}{bcdefg}

                compareStrings{Abcdefg}{bcdefg}

                compareStrings{Bbcdefg}{acdefg}

                compareStrings{bbcdefg}{acdefg}

                compareStrings{bcdefg}{bcdeag}

                compareStrings{ABcDeF}{aBCdef}


                The pdftexcmds package defines pdf@strcmp to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result is



                abcdefg -- bcdefg: -1
                Abcdefg -- bcdefg: -1
                Bbcdefg -- acdefg: 1
                bbcdefg -- acdefg: 1
                bcdefg -- bcdeag: 1
                ABcDeF -- aBCdef: 0


                The edef allows also to pass macros to compareStrings, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).



                If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:



                makeatletter
                newcommandcompareStringsDo[5]{%
                lowercase{ifcasepdf@strcmp{#1}{#2}}%
                #4or
                #5else
                #3fi
                }
                makeatother


                So with compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>} the <before> code will be executed when <str1> comes before <str2> in the alphabetical order, <equal> if they are the same and <after> otherwise (after normalization to lowercase).



                An expl3 version that has the big advantage of being fully expandable.



                documentclass{article}
                usepackage{xparse}

                ExplSyntaxOn
                NewExpandableDocumentCommand{compareStrings}{mm}
                {
                str_if_eq:eeTF { str_lower_case:f { #1 } } { str_lower_case:f { #2 } }
                { equalStrings{#1}{#2} }
                { differentStrings{#1}{#2} }
                }
                ExplSyntaxOff

                newcommand{equalStrings}[2]{typeout{Strings #1 and #2 are equal}}
                newcommand{differentStrings}[2]{typeout{Strings #1 and #2 are different}}

                newcommand{test}{AbCdEF}

                compareStrings{abcdefg}{bcdefg}

                compareStrings{Abcdefg}{bcdefg}

                compareStrings{Bbcdefg}{acdefg}

                compareStrings{bbcdefg}{acdefg}

                compareStrings{bcdefg}{bcdeag}

                compareStrings{ABcDeF}{aBCdef}

                compareStrings{ABcDeF}{test}

                stop


                The console output:



                Strings abcdefg and bcdefg are different
                Strings Abcdefg and bcdefg are different
                Strings Bbcdefg and acdefg are different
                Strings bbcdefg and acdefg are different
                Strings bcdefg and bcdeag are different
                Strings ABcDeF and aBCdef are equal
                Strings ABcDeF and AbCdEF are equal






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 55 mins ago

























                answered May 30 '12 at 15:50









                egreg

                708k8618813162




                708k8618813162























                    9














                    Old, simple, not-really-the-answer-kind-of-answer



                    [kept for 'historical purposes' - can be deleted anytime]



                    I'm no big LaTeX wizard as egreg for instance. :) So I propose a much simpler solution, to simply use a package out there: xstring:



                    documentclass{article}

                    usepackage{xstring}

                    begin{document}

                    IfStrEq{abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bcdefg}{bcdeag}{true}{false}
                    IfStrEq{bcdeag}{bcdeag}{true}{false}

                    end{document}


                    The command is really simple to use: it takes 4 arguments, the first two are the strings to be compared, the 3rd is to be executed when the comparison result is true, otherwise argument number 4 will be executed.



                    The package provides a lot more functions for fancy string manipulations.





                    EDIT: New, corrected answer (still using xstring)



                    After posting my first answer, I was told (rightfully!) that the question was about more than just a simple equality check. Rather it is about comparing whether a string comes before or after another one alphabetically. After scratching my head a bit, I came up with this:



                    documentclass{article}

                    usepackage{xstring}
                    usepackage[nomessages]{fp}

                    newcommand{compAlph}[2]{%

                    StrCompare{#1}{#2}[posdiff]

                    Difference between input strings detected at position:

                    posdiffsmallskip

                    StrChar{#1}{posdiff}[myfirstchar]

                    Character in the 1st string that is different:

                    myfirstcharsmallskip

                    StrChar{#2}{posdiff}[mysecondchar]

                    Character in the 2nd string that is different:

                    mysecondcharsmallskip

                    StrPosition{abcdefghijklmnopqrstuvwxyz}{myfirstchar}[posfirst]
                    StrPosition{abcdefghijklmnopqrstuvwxyz}{mysecondchar}[possecond]

                    FPeval{posrel}{clip(possecond-posfirst)}
                    `Relative distance' between characters:

                    posrel
                    }

                    begin{document}

                    compAlph{zyzzyzzyryx}{bcdeag}
                    bigskip
                    compAlph{abcdefg}{bcdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bcdefg}{bcdeag}
                    bigskip
                    compAlph{bcdeag}{bcdeag}

                    end{document}


                    The 'relative distance' thing shows actually, 'how far apart' in the defined alphabet the characters are that differ. If the value is negative, the second word would need to move 'up', before the other word to have them in alphabetical order, and the other way around if it is positive.



                    It is not as elegant as egreg's solution and prints the result into the document, it also might seem a bit crude and may need a bit of tuning, but it's an alternative. :)






                    share|improve this answer























                    • The OP, however, needs not to check for equality, but for alphabetic order.
                      – Daniel
                      May 30 '12 at 16:34










                    • @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                      – Count Zero
                      May 30 '12 at 17:17










                    • Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                      – Count Zero
                      May 31 '12 at 11:04
















                    9














                    Old, simple, not-really-the-answer-kind-of-answer



                    [kept for 'historical purposes' - can be deleted anytime]



                    I'm no big LaTeX wizard as egreg for instance. :) So I propose a much simpler solution, to simply use a package out there: xstring:



                    documentclass{article}

                    usepackage{xstring}

                    begin{document}

                    IfStrEq{abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bcdefg}{bcdeag}{true}{false}
                    IfStrEq{bcdeag}{bcdeag}{true}{false}

                    end{document}


                    The command is really simple to use: it takes 4 arguments, the first two are the strings to be compared, the 3rd is to be executed when the comparison result is true, otherwise argument number 4 will be executed.



                    The package provides a lot more functions for fancy string manipulations.





                    EDIT: New, corrected answer (still using xstring)



                    After posting my first answer, I was told (rightfully!) that the question was about more than just a simple equality check. Rather it is about comparing whether a string comes before or after another one alphabetically. After scratching my head a bit, I came up with this:



                    documentclass{article}

                    usepackage{xstring}
                    usepackage[nomessages]{fp}

                    newcommand{compAlph}[2]{%

                    StrCompare{#1}{#2}[posdiff]

                    Difference between input strings detected at position:

                    posdiffsmallskip

                    StrChar{#1}{posdiff}[myfirstchar]

                    Character in the 1st string that is different:

                    myfirstcharsmallskip

                    StrChar{#2}{posdiff}[mysecondchar]

                    Character in the 2nd string that is different:

                    mysecondcharsmallskip

                    StrPosition{abcdefghijklmnopqrstuvwxyz}{myfirstchar}[posfirst]
                    StrPosition{abcdefghijklmnopqrstuvwxyz}{mysecondchar}[possecond]

                    FPeval{posrel}{clip(possecond-posfirst)}
                    `Relative distance' between characters:

                    posrel
                    }

                    begin{document}

                    compAlph{zyzzyzzyryx}{bcdeag}
                    bigskip
                    compAlph{abcdefg}{bcdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bcdefg}{bcdeag}
                    bigskip
                    compAlph{bcdeag}{bcdeag}

                    end{document}


                    The 'relative distance' thing shows actually, 'how far apart' in the defined alphabet the characters are that differ. If the value is negative, the second word would need to move 'up', before the other word to have them in alphabetical order, and the other way around if it is positive.



                    It is not as elegant as egreg's solution and prints the result into the document, it also might seem a bit crude and may need a bit of tuning, but it's an alternative. :)






                    share|improve this answer























                    • The OP, however, needs not to check for equality, but for alphabetic order.
                      – Daniel
                      May 30 '12 at 16:34










                    • @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                      – Count Zero
                      May 30 '12 at 17:17










                    • Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                      – Count Zero
                      May 31 '12 at 11:04














                    9












                    9








                    9






                    Old, simple, not-really-the-answer-kind-of-answer



                    [kept for 'historical purposes' - can be deleted anytime]



                    I'm no big LaTeX wizard as egreg for instance. :) So I propose a much simpler solution, to simply use a package out there: xstring:



                    documentclass{article}

                    usepackage{xstring}

                    begin{document}

                    IfStrEq{abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bcdefg}{bcdeag}{true}{false}
                    IfStrEq{bcdeag}{bcdeag}{true}{false}

                    end{document}


                    The command is really simple to use: it takes 4 arguments, the first two are the strings to be compared, the 3rd is to be executed when the comparison result is true, otherwise argument number 4 will be executed.



                    The package provides a lot more functions for fancy string manipulations.





                    EDIT: New, corrected answer (still using xstring)



                    After posting my first answer, I was told (rightfully!) that the question was about more than just a simple equality check. Rather it is about comparing whether a string comes before or after another one alphabetically. After scratching my head a bit, I came up with this:



                    documentclass{article}

                    usepackage{xstring}
                    usepackage[nomessages]{fp}

                    newcommand{compAlph}[2]{%

                    StrCompare{#1}{#2}[posdiff]

                    Difference between input strings detected at position:

                    posdiffsmallskip

                    StrChar{#1}{posdiff}[myfirstchar]

                    Character in the 1st string that is different:

                    myfirstcharsmallskip

                    StrChar{#2}{posdiff}[mysecondchar]

                    Character in the 2nd string that is different:

                    mysecondcharsmallskip

                    StrPosition{abcdefghijklmnopqrstuvwxyz}{myfirstchar}[posfirst]
                    StrPosition{abcdefghijklmnopqrstuvwxyz}{mysecondchar}[possecond]

                    FPeval{posrel}{clip(possecond-posfirst)}
                    `Relative distance' between characters:

                    posrel
                    }

                    begin{document}

                    compAlph{zyzzyzzyryx}{bcdeag}
                    bigskip
                    compAlph{abcdefg}{bcdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bcdefg}{bcdeag}
                    bigskip
                    compAlph{bcdeag}{bcdeag}

                    end{document}


                    The 'relative distance' thing shows actually, 'how far apart' in the defined alphabet the characters are that differ. If the value is negative, the second word would need to move 'up', before the other word to have them in alphabetical order, and the other way around if it is positive.



                    It is not as elegant as egreg's solution and prints the result into the document, it also might seem a bit crude and may need a bit of tuning, but it's an alternative. :)






                    share|improve this answer














                    Old, simple, not-really-the-answer-kind-of-answer



                    [kept for 'historical purposes' - can be deleted anytime]



                    I'm no big LaTeX wizard as egreg for instance. :) So I propose a much simpler solution, to simply use a package out there: xstring:



                    documentclass{article}

                    usepackage{xstring}

                    begin{document}

                    IfStrEq{abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Abcdefg}{bcdefg}{true}{false}
                    IfStrEq{Bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bbcdefg}{acdefg}{true}{false}
                    IfStrEq{bcdefg}{bcdeag}{true}{false}
                    IfStrEq{bcdeag}{bcdeag}{true}{false}

                    end{document}


                    The command is really simple to use: it takes 4 arguments, the first two are the strings to be compared, the 3rd is to be executed when the comparison result is true, otherwise argument number 4 will be executed.



                    The package provides a lot more functions for fancy string manipulations.





                    EDIT: New, corrected answer (still using xstring)



                    After posting my first answer, I was told (rightfully!) that the question was about more than just a simple equality check. Rather it is about comparing whether a string comes before or after another one alphabetically. After scratching my head a bit, I came up with this:



                    documentclass{article}

                    usepackage{xstring}
                    usepackage[nomessages]{fp}

                    newcommand{compAlph}[2]{%

                    StrCompare{#1}{#2}[posdiff]

                    Difference between input strings detected at position:

                    posdiffsmallskip

                    StrChar{#1}{posdiff}[myfirstchar]

                    Character in the 1st string that is different:

                    myfirstcharsmallskip

                    StrChar{#2}{posdiff}[mysecondchar]

                    Character in the 2nd string that is different:

                    mysecondcharsmallskip

                    StrPosition{abcdefghijklmnopqrstuvwxyz}{myfirstchar}[posfirst]
                    StrPosition{abcdefghijklmnopqrstuvwxyz}{mysecondchar}[possecond]

                    FPeval{posrel}{clip(possecond-posfirst)}
                    `Relative distance' between characters:

                    posrel
                    }

                    begin{document}

                    compAlph{zyzzyzzyryx}{bcdeag}
                    bigskip
                    compAlph{abcdefg}{bcdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bbcdefg}{acdefg}
                    bigskip
                    compAlph{bcdefg}{bcdeag}
                    bigskip
                    compAlph{bcdeag}{bcdeag}

                    end{document}


                    The 'relative distance' thing shows actually, 'how far apart' in the defined alphabet the characters are that differ. If the value is negative, the second word would need to move 'up', before the other word to have them in alphabetical order, and the other way around if it is positive.



                    It is not as elegant as egreg's solution and prints the result into the document, it also might seem a bit crude and may need a bit of tuning, but it's an alternative. :)







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 31 '12 at 11:14

























                    answered May 30 '12 at 15:54









                    Count Zero

                    12.9k64492




                    12.9k64492












                    • The OP, however, needs not to check for equality, but for alphabetic order.
                      – Daniel
                      May 30 '12 at 16:34










                    • @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                      – Count Zero
                      May 30 '12 at 17:17










                    • Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                      – Count Zero
                      May 31 '12 at 11:04


















                    • The OP, however, needs not to check for equality, but for alphabetic order.
                      – Daniel
                      May 30 '12 at 16:34










                    • @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                      – Count Zero
                      May 30 '12 at 17:17










                    • Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                      – Count Zero
                      May 31 '12 at 11:04
















                    The OP, however, needs not to check for equality, but for alphabetic order.
                    – Daniel
                    May 30 '12 at 16:34




                    The OP, however, needs not to check for equality, but for alphabetic order.
                    – Daniel
                    May 30 '12 at 16:34












                    @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                    – Count Zero
                    May 30 '12 at 17:17




                    @Daniel: I see... I just thought it was a simple comparison - my bad. Then xstring is not the right tool, since you need to do something like < or > operations (which it doesn't provide). I'll delete my post. Thanks anyway. :)
                    – Count Zero
                    May 30 '12 at 17:17












                    Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                    – Count Zero
                    May 31 '12 at 11:04




                    Well... on second thought I won't! :) There is a solution using xstring. See my edit. ;)
                    – Count Zero
                    May 31 '12 at 11:04


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


                    • 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%2ftex.stackexchange.com%2fquestions%2f57887%2falphabetic-comparison-of-two-strings%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

                    Accessing regular linux commands in Huawei's Dopra Linux

                    Can't connect RFCOMM socket: Host is down

                    Kernel panic - not syncing: Fatal Exception in Interrupt