Alphabetic comparison of two strings
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
add a comment |
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
add a comment |
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
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
strings comparison
edited May 30 '12 at 15:41
Claudio Fiandrino
52.1k11152306
52.1k11152306
asked May 30 '12 at 15:37
Caio
17718
17718
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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
add a comment |
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. :)
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. Thenxstring
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 usingxstring
. See my edit.;)
– Count Zero
May 31 '12 at 11:04
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
add a comment |
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
add a comment |
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
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
edited 55 mins ago
answered May 30 '12 at 15:50
egreg
708k8618813162
708k8618813162
add a comment |
add a comment |
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. :)
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. Thenxstring
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 usingxstring
. See my edit.;)
– Count Zero
May 31 '12 at 11:04
add a comment |
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. :)
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. Thenxstring
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 usingxstring
. See my edit.;)
– Count Zero
May 31 '12 at 11:04
add a comment |
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. :)
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. :)
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. Thenxstring
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 usingxstring
. See my edit.;)
– Count Zero
May 31 '12 at 11:04
add a comment |
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. Thenxstring
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 usingxstring
. 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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