String comparison: Difference between revisions
Nimrod -> Nim |
|||
Line 1,029: | Line 1,029: | ||
> : true |
> : true |
||
>= : true</pre> |
>= : true</pre> |
||
=={{header|Oforth}}== |
|||
<lang Oforth>"abcd" "abcd" == |
|||
"abcd" "abce" <> |
|||
"abcd" "abceed" <= |
|||
"abce" "abcd" > |
|||
"abdEEE" toUpper "ABCeee" toUpper ==</lang> |
|||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
Revision as of 14:06, 10 January 2015
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Basic Data Operation
This is a basic data operation. It represents a fundamental action on a basic data type.
You may see other such operations in the Basic Data Operations category, or:
Integer Operations
Arithmetic |
Comparison
Boolean Operations
Bitwise |
Logical
String Operations
Concatenation |
Interpolation |
Comparison |
Matching
Memory Operations
Pointers & references |
Addresses
The task is to demonstrate how to compare two strings from within the language and how to achieve a lexical comparison.
The task should demonstrate:
- Comparing two strings for exact equality
- Comparing two strings for inequality (i.e., the inverse of exact equality)
- Comparing two strings to see if one is lexically ordered before than the other
- Comparing two strings to see if one is lexically ordered after than the other
- How to achieve both case sensitive comparisons and case insensitive comparisons within the language
- How the language handles comparison of numeric strings if these are not treated lexically
- Demonstrate any other kinds of string comparisons that the language provides, particularly as it relates to your type system. For example, you might demonstrate the difference between generic/polymorphic comparison and coercive/allomorphic comparison if your language supports such a distinction.
Here "generic/polymorphic" comparison means that the function or operator you're using doesn't always do string comparison, but bends the actual semantics of the comparison depending on the types one or both arguments; with such an operator, you achieve string comparison only if the arguments are sufficiently string-like in type or appearance. In contrast, a "coercive/allomorphic" comparison function or operator has fixed string-comparison semantics regardless of the argument type; instead of the operator bending, it's the arguments that are forced to bend instead and behave like strings if they can, and the operator simply fails if the arguments cannot be viewed somehow as strings. A language may have one or both of these kinds of operators; see the Perl 6 entry for an example of a language with both kinds of operators.
See also:
Ada
Ada uses the usual comparison operators ("=" for equality, "/=" for not being equal, ect.) for strings. One uses the same comparison operators to compare variables of other types (integers, floating point numbers, ect.). But, as Ada is strongly typed, comparing two objects of different type is not possible. To compare, say, a string and an integer, one would need to call an explicit type conversion for one of these objects.
String comparisons are case sensitive. Case insensitive comparisons have to use some conversion operation, such as Ada.Characters.Handling.To_Lower from the standard library, cf. [[1]]
<lang Ada>with Ada.Text_IO, Ada.Strings.Equal_Case_Insensitive;
procedure String_Compare is
procedure Print_Comparison (A, B: String) is use Ada.Text_IO; Function eq(Left, Right : String) return Boolean renames Ada.Strings.Equal_Case_Insensitive; begin Put_Line
( """" & A & """ and """ & B & """: " & (if A = B then "equal, " elsif eq(A,B) then "case-insensitive-equal, " else "not equal at all, ") & (if A /= B then "/=, " else "") & (if A < B then "before, " else "") & (if A > B then "after, " else "") & (if A <= B then "<=, " else "(not <=), ") & "and " & (if A >= B then ">=. " else "(not >=).") );
end Print_Comparison;
begin
Print_Comparison("this", "that"); Print_Comparison("that", "this"); Print_Comparison("THAT", "That"); Print_Comparison("this", "This"); Print_Comparison("this", "this"); Print_Comparison("the", "there"); Print_Comparison("there", "the");
end String_Compare;</lang>
- Output:
"this" and "that": not equal at all, /=, after, (not <=), and >=. "that" and "this": not equal at all, /=, before, <=, and (not >=). "THAT" and "That": case-insensitive-equal, /=, before, <=, and (not >=). "this" and "This": case-insensitive-equal, /=, after, (not <=), and >=. "this" and "this": equal, <=, and >=. "the" and "there": not equal at all, /=, before, <=, and (not >=). "there" and "the": not equal at all, /=, after, (not <=), and >=.
Aime
<lang aime>text s, t;
s = "occidental"; t = "oriental";
- operator case sensitive comparison
o_form("~ vs ~ (==, !=, <, <=, >=, >): ~ ~ ~ ~ ~ ~\n", s, t, s == t, s != t, s < t, s <= t, s >= t, s > t);
s = "Oriental"; t = "oriental";
- case sensitive comparison
o_form("~ vs ~ (==, !=, <, >): ~ ~ ~ ~\n", s, t, !compare(s, t), compare(s, t), compare(s, t) < 0, 0 < compare(s, t));
- case insensitive comparison
o_form("~ vs ~ (==, !=, <, >): ~ ~ ~ ~\n", s, t, !icompare(s, t), icompare(s, t), icompare(s, t) < 0, 0 < icompare(s, t));</lang>
- Output:
occidental vs oriental (==, !=, <, <=, >=, >): 0 -15 1 1 0 0 Oriental vs oriental (==, !=, <, >): 0 -32 1 0 Oriental vs oriental (==, !=, <, >): 1 0 0 0
AWK
In awk, the string matching operators are case sensitive, and the behaviour of the comparative operators depends on the locale being used.
Be very careful with numeric strings, because whether they will be treated as numeric values or strings depends on how the values were obtained, and on which awk interpreter is being used.
Numeric strings obtained from the input source, will be treated as numeric values, when compared with other strings containing numeric values.
Strings valued defined as constants using doublequote enclosures will be treated as strings of characters and compared lexically.
The behaviour of the operators when one value is considered to be numeric (eg. from the input source), but the other value has been defined explicitly as a numeric string by using doublequote enclosures may also vary depending on which awk interpreter is being used.
<lang awk>BEGIN {
a="BALL" b="BELL"
if (a == b) { print "The strings are equal" } if (a != b) { print "The strings are not equal" } if (a > b) { print "The first string is lexically after than the second" } if (a < b) { print "The first string is lexically before than the second" } if (a >= b) { print "The first string is not lexically before than the second" } if (a <= b) { print "The first string is not lexically after than the second" }
# to make a case insensitive comparison convert both strings to the same lettercase: a="BALL" b="ball" if (tolower(a) == tolower(b)) { print "The first and second string are the same disregarding letter case" }
}</lang>
BASIC
<lang basic>10 LET "A$="BELL" 20 LET B$="BELT" 30 IF A$ = B$ THEN PRINT "THE STRINGS ARE EQUAL": REM TEST FOR EQUALITY 40 IF A$ <> B$ THEN PRINT "THE STRINGS ARE NOT EQUAL": REM TEST FOR INEQUALITY 50 IF A$ > B$ THEN PRINT A$;" IS LEXICALLY HIGHER THAN ";B$: REM TEST FOR LEXICALLY HIGHER 60 IF A$ < B$ THEN PRINT A$;" IS LEXICALLY LOWER THAN ";B$: REM TEST FOR LEXICALLY LOWER 70 IF A$ <= B$ THEN PRINT A$;" IS NOT LEXICALLY HIGHER THAN ";B$ 80 IF A$ >= B$ THEN PRINT A$;" IS NOT LEXICALLY LOWER THAN ";B$ 90 END</lang>
On a platform that supports both uppercase and lowercase characters, the string comparitive operators are case sensitive. To perform case insensitive matching, make sure both strings are converted to the same lettercase. Here we assume that the BASIC has the UPPER$ and LOWER$ keyword pair for case conversion. If not, then some number crunching based on the character codes is required. (In Ascii add 32 to uppercase letter codes to get the lowercase equivalent). Note that any whitespace within the strings must also match exactly for the strings to be considered equal.
<lang basic>10 LET A$="BELT" 20 LET B$="belt" 30 IF UPPER$(A$)=UPPER$(B$) THEN PRINT "Disregarding lettercase, the strings are the same."</lang>
Applesoft BASIC
For case sensitive comparisons
Applesoft BASIC does not have a built in UPPER$ function.
Bracmat
String comparison in Bracmat is performed by string pattern matching using an atomic pattern. Bracmat has two pattern matching regimes. Originally, pattern matching was only done on tree structures, with patterns mimicking the subject tree to match. Later string pattern matching was introduced. String pattern matching is discernible from the original pattern matching by the prefix @
. String pattern matching requires that the subject is atomic. Patterns for string matching can be as complex as patterns used for matching structures. String comparison is a very simple string pattern matching operation requiring just an atomic pattern, combined with some prefixes if needed.
The atomic pattern can be prefixed with <
(less than), >
(greater than), ~
(not) or %
(coerces string matching) or combinations thereof. If both sides of the match operator :
are numbers, Bracmat does a numerice comparison, unless the pattern (the rhs) has the prefix %
.
<lang bracmat>( {Comparing two strings for exact equality}
& ( ( @(abc:abc)
& @(123:%123) {Previous pairs of strings are exactly equal} ) & ( @(abc:Abc) | @(123:%246/2) | @(abc:ab) | @(123:%12) | {Previous pairs of strings are not exactly equal} ) ) {Comparing two strings for inequality (i.e., the inverse of exact equality)}
& ( ( @(abc:~<>abc)
& @(abc:~<>Abc) {Previous pairs of strings are more or less equal} ) & ( @(abc:~<>ab) | {Previous pairs of strings are not more or less equal} ) ) {Comparing two strings to see if one is lexically ordered before than the other}
& ( ( @(Abc:<abc)
& @(Abc:<a) & @(123:<%246/2) & @(123:<%2) & @(12:<%123) & @(ab:<abc) {Previous pairs of strings are lexically ordered one before the other} ) & ( @(abc:<abc) | @(abc:<Abc) | @(246/2:<%123) | @(abc:<ab) | @(123:<%12) | @(123:<%123) | {Previous pairs of strings are not lexically ordered one before the other} ) ) {Comparing two strings to see if one is lexically ordered after than the other}
& ( ( @(abc:>Abc)
& @(a:>Abc) & @(246/2:>%123) & @(2:>%123) & @(123:>%12) & @(abc:>ab) {Previous pairs of strings are lexically ordered one after the other} ) & ( @(abc:>abc) | @(Abc:>abc) | @(123:>%246/2) | @(ab:>abc) | @(12:>%123) | @(123:>%123) | {Previous pairs of strings are not lexically ordered one after the other} ) ) {How to achieve both case sensitive comparisons and case insensitive comparisons within the language}
& ( ( @(abc:~<>abc)
& @(abc:~<>Abc) & @(БЪЛГАРСКИ:~<>български) {Previous pairs of strings are more or less equal} ) & ( @(abc:~<>ab) | {Previous pairs of strings are not more or less equal} ) ) {How the language handles comparison of numeric strings if these are not treated lexically}
& ( ( @(246/2:123)
& @(2:<123) & @(123:>12) & @(123:246/2) & @(12:<123) {Previous numeric string comparisons succeed} ) & ( @(123:<246/2) | @(12:>123) | @(123:>123) | @(123:~123) | {Previous numeric string comparisons fail} ) ) {Demonstrate any other kinds of string comparisons that the language provides, particularly
as it relates to your type system. For example, you might demonstrate the difference between generic/polymorphic comparison and coercive/allomorphic comparison if your language supports such a distinction.} & ( ( @(246/2:>12--3)
& @(2:>123kg) & @(123:<12d) & @(123:~24/6/2) & @(12a:>123) {Previous coercive string comparisons succeed} ) & ( @(2013-05-01:20130501) | @(246/2a:123a) | @(1239:<123-) | {Previous coercive string comparisons fail} ) )
& done );</lang>
Burlesque
<lang burlesque> blsq ) "abc""abc"== 1 blsq ) "abc""abc"!= 0 blsq ) "abc""Abc"cm 1 blsq ) "ABC""Abc"cm -1 </lang>
cm is used for comparision which returns 1,0,-1 like C's strcmp. == is Equal and != is NotEqual.
C
Solution C provides the strcmp and strcasecmp functions for lexical comparison of ASCIIz strings, with declarations found in string.h . strcmp causes a good deal of confusion because it returns 0 when the strings are equal. Hence the likely looking common mistake <lang c> /* WRONG! */ if (strcmp(a,b)) action_on_equality(); </lang> Wrapping strcmp with macros or functions makes good sense. c has other functions to compare binary data, version strings, wide character strings, and strings in current locale. These behave similarly. <lang c> /*
compilation and test in bash $ a=./c && make $a && $a ball bell ball ball YUP YEP ball BELL ball BALL YUP yep cc -Wall -c -o c.o c.c eq , ne , gt , lt , ge , le ball 0 1 0 1 0 1 bell ball 0 1 0 1 0 1 bell ignoring case ball 1 0 0 0 1 1 ball ball 1 0 0 0 1 1 ball ignoring case YUP 0 1 1 0 1 0 YEP YUP 0 1 1 0 1 0 YEP ignoring case ball 0 1 1 0 1 0 BELL ball 0 1 0 1 0 1 BELL ignoring case ball 0 1 1 0 1 0 BALL ball 1 0 0 0 1 1 BALL ignoring case YUP 0 1 0 1 0 1 yep YUP 0 1 1 0 1 0 yep ignoring case
- /
- include<string.h>
- define STREQ(A,B) (0==strcmp((A),(B)))
- define STRNE(A,B) (!STREQ(A,B))
- define STRLT(A,B) (strcmp((A),(B))<0)
- define STRLE(A,B) (strcmp((A),(B))<=0)
- define STRGT(A,B) STRLT(B,A)
- define STRGE(A,B) STRLE(B,A)
- define STRCEQ(A,B) (0==strcasecmp((A),(B)))
- define STRCNE(A,B) (!STRCEQ(A,B))
- define STRCLT(A,B) (strcasecmp((A),(B))<0)
- define STRCLE(A,B) (strcasecmp((A),(B))<=0)
- define STRCGT(A,B) STRCLT(B,A)
- define STRCGE(A,B) STRCLE(B,A)
- include<stdio.h>
void compare(const char*a, const char*b) {
printf("%s%2d%2d%2d%2d%2d%2d %s\n",
a, STREQ(a,b), STRNE(a,b), STRGT(a,b), STRLT(a,b), STRGE(a,b), STRLE(a,b), b ); } void comparecase(const char*a, const char*b) {
printf("%s%2d%2d%2d%2d%2d%2d %s ignoring case\n",
a, STRCEQ(a,b), STRCNE(a,b), STRCGT(a,b), STRCLT(a,b), STRCGE(a,b), STRCLE(a,b), b ); } int main(int ac, char*av[]) {
char*a,*b; puts("\teq , ne , gt , lt , ge , le"); while (0 < (ac -= 2)) { a = *++av, b = *++av; compare(a, b); comparecase(a, b); } return 0;
} </lang>
Clipper
We will compare two strings, s1 and s2. The following comparisons are case sensitive. <lang clipper> IF s1 == s2
? "The strings are equal" ENDIF IF .NOT. (s1 == s2) ? "The strings are not equal" ENDIF IF s1 > s2 ? "s2 is lexically ordered before than s1" ENDIF IF s1 < s2 ? "s2 is lexically ordered after than s1" ENDIF</lang>
To achieve case insensitive comparisons, we should use Upper() or Lower() functions: <lang clipper> IF Upper(s1) == Upper(s2)
? "The strings are equal" ENDIF
</lang>
COBOL
Strings can be compared using the normal conditional syntax, like so: <lang cobol>"hello" = "hello" *> equality "helloo" <> "hello" *> inequality "aello" < "hello" *> lexical ordering</lang>
COBOL 2002 introduced the intrinsic functions LOCALE-COMPARE
and STANDARD-COMPARE
, which return one of the strings "="
, ">"
or "<"
depending on their parameters.
<lang cobol>FUNCTION STANDARD-COMPARE("hello", "hello") *> "="
FUNCTION STANDARD-COMPARE("aello", "hello") *> "<"
FUNCTION STANDARD-COMPARE("hello", "aello") *> ">"</lang>
Trailing spaces in strings are removed when strings are compared. However, if the strings are then of unequal length, then the shorter string is padded with spaces. <lang cobol>"hello " = "hello" *> True X"00" > X"0000" *> True</lang>
Common Lisp
There are case-sensitive and case-insensitive comparison functions. All inequality comparison functions return an integer instead of simply T
(for true) which is the position of the first character at which the strings differ.
Case-sensitive comparison functions: <lang lisp>>(string= "foo" "foo") T > (string= "foo" "FOO") NIL > (string/= "foo" "bar") 0 > (string/= "bar" "baz") 2 > (string/= "foo" "foo") NIL > (string> "foo" "Foo") 0 > (string< "foo" "Foo") NIL > (string>= "FOo" "Foo") NIL > (string<= "FOo" "Foo") 1</lang>
Case-insensitive comparison functions: <lang lisp>> (string-equal "foo" "FOo") T > (string-not-equal "foo" "FOO") NIL > (string-greaterp "foo" "Foo") NIL > (string-lessp "BAR" "foo") 0 > (string-not-greaterp "foo" "Foo") 3 > (string-not-lessp "baz" "bAr") 2</lang>
Numeric strings are always compared lexically: <lang lisp>> (string> "45" "12345") 0 > (string> "45" "9") NIL</lang>
Component Pascal
BlackBox Component Builder <lang oberon2>MODULE StringComparision; IMPORT StdLog,Strings;
PROCEDURE Do*; VAR str1,str2,aux1,aux2: ARRAY 128 OF CHAR; BEGIN str1 := "abcde";str2 := "abcde"; StdLog.String(str1+" equals " + str2 + ":> ");StdLog.Bool(str1 = str2);StdLog.Ln; str2 := "abcd"; StdLog.String(str1+" equals " + str2 + ":> ");StdLog.Bool(str1 = str2);StdLog.Ln; StdLog.String(str1+" greater than " + str2 + ":> ");StdLog.Bool(str1 > str2);StdLog.Ln; StdLog.String(str1+" lower than " + str2 + ":> ");StdLog.Bool(str1 < str2);StdLog.Ln;
str2 := "ABCDE"; StdLog.String(str1+" equals " + str2 + ":> ");StdLog.Bool(str1 = str2);StdLog.Ln; StdLog.String(str1+" greater than " + str2 + ":> ");StdLog.Bool(str1 > str2);StdLog.Ln; StdLog.String(str1+" lower than " + str2 + ":> ");StdLog.Bool(str1 < str2);StdLog.Ln;
Strings.ToLower(str1,aux1);Strings.ToLower(str2,aux2); StdLog.String(str1+" equals (case insensitive) " + str2 + ":> ");StdLog.Bool(aux1 = aux2);StdLog.Ln;
str1 := "01234";str2 := "01234"; StdLog.String(str1+" equals " + str2 + ":> ");StdLog.Bool(str1 = str2);StdLog.Ln; str2 := "0123"; StdLog.String(str1+" equals " + str2 + ":> ");StdLog.Bool(str1 = str2);StdLog.Ln; StdLog.String(str1+" greater than " + str2 + ":> ");StdLog.Bool(str1 > str2);StdLog.Ln; StdLog.String(str1+" lower than " + str2 + ":> ");StdLog.Bool(str1 < str2);StdLog.Ln; END Do;
END StringComparision.</lang>
Execute: ^Q StringComparision.Do
Output:
abcde equals abcde:> $TRUE abcde equals abcd:> $FALSE abcde greater than abcd:> $TRUE abcde lower than abcd:> $FALSE abcde equals ABCDE:> $FALSE abcde greater than ABCDE:> $TRUE abcde lower than ABCDE:> $FALSE abcde equals (case insensitive) ABCDE:> $TRUE 01234 equals 01234:> $TRUE 01234 equals 0123:> $FALSE 01234 greater than 0123:> $TRUE 01234 lower than 0123:> $FALSE
D
See also Empty_string <lang d>import std.stdio, std.string, std.algorithm;
void main() {
auto s = "abcd";
/* Comparing two strings for exact equality */ assert (s == "abcd"); // same object
/* Comparing two strings for inequality */ assert(s != "ABCD"); // different objects
/* Comparing the lexical order of two strings; -1 means smaller, 0 means equal, 1 means larger */ assert(s.icmp("Bcde") == -1); // case insensitive assert(s.cmp("Bcde") == 1); // case sensitive
assert(s.icmp("Aabc") == 1); // case insensitive assert(s.cmp("Aabc") == 1); // case sensitive assert(s.icmp("ABCD") == 0); // case insensitive assert(s.cmp("ABCD") == 1); // case sensitive
}</lang>
Erlang
Examples from Erlang shell:
<lang Erlang> 10> V = "abcd". "abcd" 11> V =:= "abcd". true 12> V =/= "abcd". false 13> V < "b". true 15> V > "aa". true 16> string:to_lower(V) =:= string:to_lower("ABCD"). true </lang>
F#
As a .NET language F# can make use of the System.String class. As strict strongly typed language F# never coerces any other type to string. System.String implements Compare function variants which are told by a StringComparison enumeration value how to compare, which might be "culture sensitive" or use an "ordinal comparison". Both of these might also be of the IgnoreCase variant. <lang fsharp>open System
// self defined operators for case insensitive comparison let (<~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) < 0 let (<=~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) <= 0 let (>~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) > 0 let (>=~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) >= 0 let (=~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) = 0 let (<>~) a b = String.Compare(a, b, StringComparison.OrdinalIgnoreCase) <> 0
let compare a b = // standard operators:
if a < b then printfn "%s is strictly less than %s" a b if a <= b then printfn "%s is less than or equal to %s" a b if a > b then printfn "%s is strictly greater than %s" a b if a >= b then printfn "%s is greater than or equal to %s" a b if a = b then printfn "%s is equal to %s" a b if a <> b then printfn "%s is not equal to %s" a b // and our case insensitive self defined operators: if a <~ b then printfn "%s is strictly less than %s (case insensitive)" a b if a <=~ b then printfn "%s is less than or equal to %s (case insensitive)" a b if a >~ b then printfn "%s is strictly greater than %s (case insensitive)" a b if a >=~ b then printfn "%s is greater than or equal to %s (case insensitive)" a b if a =~ b then printfn "%s is equal to %s (case insensitive)" a b if a <>~ b then printfn "%s is not equal to %s (case insensitive)" a b
[<EntryPoint>]
let main argv =
compare "YUP" "YUP" compare "BALL" "BELL" compare "24" "123" compare "BELL" "bELL" 0</lang>
Output
YUP is less than or equal to YUP YUP is greater than or equal to YUP YUP is equal to YUP YUP is less than or equal to YUP (case insensitive) YUP is greater than or equal to YUP (case insensitive) YUP is equal to YUP (case insensitive) BALL is strictly less than BELL BALL is less than or equal to BELL BALL is not equal to BELL BALL is strictly less than BELL (case insensitive) BALL is less than or equal to BELL (case insensitive) BALL is not equal to BELL (case insensitive) 24 is strictly greater than 123 24 is greater than or equal to 123 24 is not equal to 123 24 is strictly greater than 123 (case insensitive) 24 is greater than or equal to 123 (case insensitive) 24 is not equal to 123 (case insensitive) BELL is strictly less than bELL BELL is less than or equal to bELL BELL is not equal to bELL BELL is less than or equal to bELL (case insensitive) BELL is greater than or equal to bELL (case insensitive) BELL is equal to bELL (case insensitive)
Forth
The ANS Forth standard has the word COMPARE to lexically compare two strings, with the same behavior as the C standard library strcmp() function.
<lang Forth>: str-eq ( str len str len -- ? ) compare 0= ;
- str-neq ( str len str len -- ? ) compare 0<> ;
- str-lt ( str len str len -- ? ) compare 0< ;
- str-gt ( str len str len -- ? ) compare 0> ;
- str-le ( str len str len -- ? ) compare 0<= ;
- str-ge ( str len str len -- ? ) compare 0>= ;</lang>
Although many Forths allow case-insensitive lookup of ASCII dictionary names for function and variable names (FIND, SEARCH-WORDLIST), this capability is not exposed for other uses in a standard way.
Go
<lang go>package main
import (
"fmt" "strings"
)
func main() {
// Go language string comparison operators: c := "cat" d := "dog" if c == d { fmt.Println(c, "is bytewise identical to", d) } if c != d { fmt.Println(c, "is bytewise different from", d) } if c > d { fmt.Println(c, "is lexically bytewise greater than", d) } if c < d { fmt.Println(c, "is lexically bytewise less than", d) } if c >= d { fmt.Println(c, "is lexically bytewise greater than or equal to", d) } if c <= d { fmt.Println(c, "is lexically bytewise less than or equal to", d) } // Go is strongly typed and will not directly compare a value of string // type to a value of numeric type.
// A case insensitive compare can be done with a function in the strings // package in the Go standard library: eqf := `when interpreted as UTF-8 and compared under Unicode
simple case folding rules.`
if strings.EqualFold(c, d) { fmt.Println(c, "equal to", d, eqf) } else { fmt.Println(c, "not equal to", d, eqf) }
// Seeing that the built in operators work bytewise and the library // case folding functions interpret UTF-8, you might then ask about // other equality and inequality tests that interpret UTF-8. // Functions for this are not in the Go standard library but are in // the Go "sub repository" at golang.org/x/text. There is support // for Unicode normalization, collation tables, and locale sensitive // comparisons.
}</lang>
- Output:
cat is bytewise different from dog cat is lexically bytewise less than dog cat is lexically bytewise less than or equal to dog cat not equal to dog when interpreted as UTF-8 and compared under Unicode simple case folding rules.
Harbour
We will compare two strings, s1 and s2. The following comparisons are case sensitive. <lang visualfoxpro>IF s1 == s2
? "The strings are equal"
ENDIF IF !( s1 == s2 )
? "The strings are not equal"
ENDIF IF s1 > s2
? "s2 is lexically ordered before than s1"
ENDIF IF s1 < s2
? "s2 is lexically ordered after than s1"
ENDIF</lang> To achieve case insensitive comparisons, we should use Upper() or Lower() functions: <lang visualfoxpro>IF Upper( s1 ) == Upper( s2 )
? "The strings are equal"
ENDIF</lang>
Haskell
Examples from the Haskell shell: <lang haskell> > "abc" == "abc" True > "abc" /= "abc" False > "abc" <= "abcd" True > "abc" <= "abC" False > "HELLOWORLD" == "HelloWorld" False > :m +Data.Char > map toLower "ABC" "abc" > map toLower "HELLOWORLD" == map toLower "HelloWorld" True </lang>
Icon and Unicon
Same in both languages.
<lang unicon>procedure main(A)
s1 := A[1] | "a" s2 := A[2] | "b" # These first four are case-sensitive s1 == s2 # Are they equal? s1 ~== s2 # Are they unequal? s1 << s2 # Does s1 come before s2? s1 >> s2 # Does s1 come after s2? map(s1) == map(s2) # Caseless comparison "123" >> "12" # Lexical comparison "123" > "12" # Numeric comparison "123" >> 12 # Lexical comparison (12 coerced into "12") "123" > 12 # Numeric comparison ("123" coerced into 123)
end</lang>
J
Solution:
The primitive -:
can be used to determine whether two strings are equivalent, but J doesn't have other inbuilt lexical comparison operators. They can defined as follows:
<lang j>eq=: -: NB. equal
ne=: -.@-: NB. not equal
gt=: {.@/:@,&boxopen *. ne NB. lexically greater than
lt=: -.@{.@/:@,&boxopen *. ne NB. lexically less than
ge=: {.@/:@,&boxopen +. eq NB. lexically greater than or equal to
le=: -.@{.@/:@,&boxopen NB. lexically less than or equal to</lang>
Usage: <lang j> 'ball' (eq , ne , gt , lt , ge , le) 'bell' 0 1 0 1 0 1
'ball' (eq , ne , gt , lt , ge , le) 'ball'
1 0 0 0 1 1
'YUP' (eq , ne , gt , lt , ge , le) 'YEP'
0 1 1 0 1 0</lang>
Java
A String object in Java represents a UTF-16 string. Comparisons are done using the equals(), equalsIgnoreCase(), compareTo(), and compareToIgnoreCase() methods. <lang java>public class Compare {
public static void main (String[] args) { compare("Hello", "Hello"); compare("5", "5.0"); compare("java", "Java"); compare("ĴÃVÁ", "ĴÃVÁ"); compare("ĴÃVÁ", "ĵãvá"); } public static void compare (String A, String B) { if (A.equals(B)) System.out.printf("'%s' and '%s' are lexically equal.", A, B); else System.out.printf("'%s' and '%s' are not lexically equal.", A, B); System.out.println();
if (A.equalsIgnoreCase(B)) System.out.printf("'%s' and '%s' are case-insensitive lexically equal.", A, B); else System.out.printf("'%s' and '%s' are not case-insensitive lexically equal.", A, B); System.out.println(); if (A.compareTo(B) < 0) System.out.printf("'%s' is lexically before '%s'.\n", A, B); else if (A.compareTo(B) > 0) System.out.printf("'%s' is lexically after '%s'.\n", A, B);
if (A.compareTo(B) >= 0) System.out.printf("'%s' is not lexically before '%s'.\n", A, B); if (A.compareTo(B) <= 0) System.out.printf("'%s' is not lexically after '%s'.\n", A, B);
System.out.printf("The lexical relationship is: %d\n", A.compareTo(B)); System.out.printf("The case-insensitive lexical relationship is: %d\n\n", A.compareToIgnoreCase(B)); }
}</lang>
- Output:
'Hello' and 'Hello' are lexically equal. 'Hello' and 'Hello' are case-insensitive lexically equal. 'Hello' is not lexically before 'Hello'. 'Hello' is not lexically after 'Hello'. The lexical relationship is: 0 The case-insensitive lexical relationship is: 0 '5' and '5.0' are not lexically equal. '5' and '5.0' are not case-insensitive lexically equal. '5' is lexically before '5.0'. '5' is not lexically after '5.0'. The lexical relationship is: -2 The case-insensitive lexical relationship is: -2 'java' and 'Java' are not lexically equal. 'java' and 'Java' are case-insensitive lexically equal. 'java' is lexically after 'Java'. 'java' is not lexically before 'Java'. The lexical relationship is: 32 The case-insensitive lexical relationship is: 0 'ĴÃVÁ' and 'ĴÃVÁ' are lexically equal. 'ĴÃVÁ' and 'ĴÃVÁ' are case-insensitive lexically equal. 'ĴÃVÁ' is not lexically before 'ĴÃVÁ'. 'ĴÃVÁ' is not lexically after 'ĴÃVÁ'. The lexical relationship is: 0 The case-insensitive lexical relationship is: 0 'ĴÃVÁ' and 'ĵãvá' are not lexically equal. 'ĴÃVÁ' and 'ĵãvá' are case-insensitive lexically equal. 'ĴÃVÁ' is lexically before 'ĵãvá'. 'ĴÃVÁ' is not lexically after 'ĵãvá'. The lexical relationship is: -1 The case-insensitive lexical relationship is: 0
jq
jq strings are JSON strings. The jq comparison operators (==, !=, <, <=, >=, >) can be used to compare strings or any JSON entities. Similarly, jq's sort and unique filters can be used to sort strings. The ordering of strings is determined by the Unicode codepoints.
<lang jq># Comparing two strings for exact equality: "this" == "this" # true "this" == "This" # false
- != is the inverse of ==
- Comparing two strings to see if one is lexically ordered before the other:
"alpha" < "beta" # true "beta" < "alpha" # false
- > is the inverse of < </lang>
Currently, jq does not have any "toupper" or "tolower" case conversion, but it is easy to define jq equivalents of ruby's downcase and upcase:<lang jq>
- Only characters A to Z are affected
def downcase:
explode | map( if 65 <= . and . <= 90 then . + 32 else . end) | implode;
- Only characters a to z are affected
def upcase:
explode | map( if 97 <= . and . <= 122 then . - 32 else . end) | implode;</lang>
With the caveat that these are what they are, case-insensitive comparisons can be achieved as illustrated by this example: <lang jq>("AtoZ" | upcase) == ("atoz" | upcase) # true</lang> Numeric strings are treated as any other JSON strings.
jq has an extensive library of built-in functions for handling strings. The most recent versions of jq (since 1.4) also have extensive support for PCRE regular expressions (regex), including named captures. Please see Builtin Operators and Functions for details.
Lasso
<lang Lasso>// Comparing two strings for exact equality "'this' == 'this': " + ('this' == 'this') // true "'this' == 'This': " + ('this' == 'This') // true, as it's case insensitive
// Comparing two strings for inequality (i.e., the inverse of exact equality) "'this' != 'this': " + ('this' != 'this')// false "'this' != 'that': " + ('this' != 'that') // true
// Comparing two strings to see if one is lexically ordered before than the other "'alpha' < 'beta': " + ('alpha' < 'beta') // true "'beta' < 'alpha': " + ('beta' < 'alpha') // false
// Comparing two strings to see if one is lexically ordered after than the other "'alpha' > 'beta': " + ('alpha' > 'beta') // false "'beta' > 'alpha': " + ('beta' > 'alpha') // true
// How to achieve both case sensitive comparisons and case insensitive comparisons within the language "case sensitive - 'this'->equals('This',-case=true): " + ('this'->equals('This',-case=true)) // false "case insensitive - 'this'->equals('This',-case=true): " + ('this'->equals('This')) // true
// How the language handles comparison of numeric strings if these are not treated lexically "'01234' == '01234': "+ ('01234' == '01234') // true "'01234' == '0123': " + ('01234' == '0123') // false "'01234' > '0123': " + ('01234' > '0123') // true "'01234' < '0123': " + ('01234' < '0123') //false
// Additional string comparisons "'The quick brown fox jumps over the rhino' >> 'fox' (contains): " +
('The quick brown fox jumps over the rhino' >> 'fox') // true
"'The quick brown fox jumps over the rhino' >> 'cat' (contains): " +
('The quick brown fox jumps over the rhino' >> 'cat') // false
"'The quick brown fox jumps over the rhino'->beginswith('rhino'): " +
('The quick brown fox jumps over the rhino'->beginswith('rhino')) // false
"'The quick brown fox jumps over the rhino'->endswith('rhino'): " +
('The quick brown fox jumps over the rhino'->endswith('rhino')) // true
</lang>
- Output:
'this' == 'this': true 'this' == 'This': true 'this' != 'this': false 'this' != 'that': true 'alpha' < 'beta': true 'beta' < 'alpha': false 'alpha' > 'beta': false 'beta' > 'alpha': true case sensitive - 'this'->equals('This',-case=true): false case insensitive - 'this'->equals('This',-case=true): true '01234' == '01234': true '01234' == '0123': false '01234' > '0123': true '01234' < '0123': false 'The quick brown fox jumps over the rhino' >> 'fox' (contains): true 'The quick brown fox jumps over the rhino' >> 'cat' (contains): false 'The quick brown fox jumps over the rhino'->beginswith('rhino'): false 'The quick brown fox jumps over the rhino'->endswith('rhino'): true
Lua
- Lua coerces numbers to strings and vice-versa if possible, but it never does this during comparisons or table indexing.
- Case-insensitivity can be accomplished by using
string.upper
orstring.lower
on both strings prior to comparing them. - Lua does not have a dedicated identity operator as == already plays that role. If two strings have equal contents, they are the same object and therefore equal.
<lang lua>function compare(a, b)
print(("%s is of type %s and %s is of type %s"):format( a, type(a), b, type(b) )) if a < b then print(('%s is strictly less than %s'):format(a, b)) end if a <= b then print(('%s is less than or equal to %s'):format(a, b)) end if a > b then print(('%s is strictly greater than %s'):format(a, b)) end if a >= b then print(('%s is greater than or equal to %s'):format(a, b)) end if a == b then print(('%s is equal to %s'):format(a, b)) end if a ~= b then print(('%s is not equal to %s'):format(a, b)) end print ""
end
compare('YUP', 'YUP') compare('BALL', 'BELL') compare('24', '123') compare(24, 123) compare(5.0, 5)</lang>
- Output:
YUP is of type string and YUP is of type string YUP is less than or equal to YUP YUP is greater than or equal to YUP YUP is equal to YUP BALL is of type string and BELL is of type string BALL is strictly less than BELL BALL is less than or equal to BELL BALL is not equal to BELL 24 is of type string and 123 is of type string 24 is strictly greater than 123 24 is greater than or equal to 123 24 is not equal to 123 24 is of type number and 123 is of type number 24 is strictly less than 123 24 is less than or equal to 123 24 is not equal to 123 5 is of type number and 5 is of type number 5 is less than or equal to 5 5 is greater than or equal to 5 5 is equal to 5
Mathematica
<lang Mathematica>compare[x_, y_] := Module[{},
If[x == y, Print["Comparing for equality (case sensitive): " <> x <> " and " <> y <> " ARE equal"], Print["Comparing for equality (case sensitive): " <> x <> " and " <> y <> " are NOT equal" ]] ; If[x != y, Print["Comparing for inequality (case sensitive): " <> x <> " and " <> y <> " are NOT equal"], Print["Comparing for inequality (case sensitive): " <> x <> " and " <> y <> " ARE equal" ]] ; Switch[Order[x, y], 1, Print["Comparing for order (case sensitive): " <> x <> " comes before " <> y], -1, Print["Comparing for order (case sensitive): " <> x <> " comes after " <> y], 0, Print["Comparing for order (case sensitive): " <> x <> " comes in the same spot as " <> y]]; If[ToLowerCase[x] == ToLowerCase[y], Print["Comparing for equality (case insensitive): " <> x <> " and " <> y <> " ARE equal"], Print["Comparing for equality (case insensitive): " <> x <> " and " <> y <> " are NOT equal" ]] ; Print[]; ]
compare["Hello", "Hello"] compare["3.1", "3.14159"] compare["mathematica", "Mathematica"]</lang>
- Output:
Comparing for equality (case sensitive): Hello and Hello ARE equal Comparing for inequality (case sensitive): Hello and Hello ARE equal Comparing for order (case sensitive): Hello comes in the same spot as Hello Comparing for equality (case insensitive): Hello and Hello ARE equal Comparing for equality (case sensitive): 3.1 and 3.14159 are NOT equal Comparing for inequality (case sensitive): 3.1 and 3.14159 are NOT equal Comparing for order (case sensitive): 3.1 comes before 3.14159 Comparing for equality (case insensitive): 3.1 and 3.14159 are NOT equal Comparing for equality (case sensitive): mathematica and Mathematica are NOT equal Comparing for inequality (case sensitive): mathematica and Mathematica are NOT equal Comparing for order (case sensitive): mathematica comes before Mathematica Comparing for equality (case insensitive): mathematica and Mathematica ARE equal
NetRexx
The only change to the REXX program to make this work in NetRexx was to change "!=" to "\=" for the NOT EQUAL comparison. (Incidentally; the form shown here will function equally well as a REXX program: "\=" is valid REXX syntax for NOT EQUAL in most dialects.)
Will not work with TSO REXX on some codepages.
Changing \= to <> would make it work everywhere. Unfortunately there is no such "cure" for \==.
See also ooRexx and REXX version 2 for caseless comparison and comparison of numbers.
<lang NetRexx>animal = 'dog'
if animal = 'cat' then
say animal "is lexically equal to cat"
if animal \= 'cat' then
say animal "is not lexically equal cat"
if animal > 'cat' then
say animal "is lexically higher than cat"
if animal < 'cat' then
say animal "is lexically lower than cat"
if animal >= 'cat' then
say animal "is not lexically lower than cat"
if animal <= 'cat' then
say animal "is not lexically higher than cat"
/* The above comparative operators do not consider
leading and trailing whitespace when making comparisons. */
if ' cat ' = 'cat' then
say "this will print because whitespace is stripped"
/* To consider all whitespace in a comparison
we need to use strict comparative operators */
if ' cat ' == 'cat' then
say "this will not print because comparison is strict"
</lang> The list of strict comparison operators described in the REXX sample apply to NetRexx too.
Nim
<lang nim>import strutils
var s1: string = "The quick brown" var s2: string = "The Quick Brown" echo("== : ", s1 == s2) echo("!= : ", s1 != s2) echo("< : ", s1 < s2) echo("<= : ", s1 <= s2) echo("> : ", s1 > s2) echo(">= : ", s1 >= s2)</lang>
- Output:
== : false != : true < : false <= : false > : true >= : true
Oforth
<lang Oforth>"abcd" "abcd" == "abcd" "abce" <> "abcd" "abceed" <= "abce" "abcd" > "abdEEE" toUpper "ABCeee" toUpper ==</lang>
ooRexx
See the NetRexx and/or the REXX implementation.
There is a way to "caseless" compare array elements: <lang>a=.array~of('A 1','B 2','a 3','b 3','A 5') a~sortwith(.caselesscomparator~new) Do i=1 To 5
Say a[i] End</lang>
Output:
A 1 a 3 A 5 B 2 b 3
PARI/GP
Strings are compared for equality and inequality with ==
and !=
and are compared with cmp
or with the usual < > <= >=
. Case-insensitive comparison is not built in.
Perl
Scalar variables are weakly typed in Perl, and there are two sets of comparison operators that can be used on them: One set for (coercive) numeric comparison, and one set for (coercive) lexical string comparison. The second set is demonstrated in the following:
<lang perl>use v5.16; # ...for fc(), which does proper Unicode casefolding.
# With older Perl versions you can use lc() as a poor-man's substitute.
sub compare {
my ($a, $b) = @_; my $A = "'$a'"; my $B = "'$b'"; print "$A and $B are lexically equal.\n" if $a eq $b; print "$A and $B are not lexically equal.\n" if $a ne $b; print "$A is lexically before $B.\n" if $a lt $b; print "$A is lexically after $B.\n" if $a gt $b; print "$A is not lexically before $B.\n" if $a ge $b; print "$A is not lexically after $B.\n" if $a le $b; print "The lexical relationship is: ", $a cmp $b, "\n"; print "The case-insensitive lexical relationship is: ", fc($a) cmp fc($b), "\n"; print "\n";
}
compare('Hello', 'Hello'); compare('5', '5.0'); compare('perl', 'Perl');</lang>
- Output:
'Hello' and 'Hello' are lexically equal. 'Hello' is not lexically before 'Hello'. 'Hello' is not lexically after 'Hello'. The lexical relationship is: 0 The case-insensitive lexical relationship is: 0 '5' and '5.0' are not lexically equal. '5' is lexically before '5.0'. '5' is not lexically after '5.0'. The lexical relationship is: -1 The case-insensitive lexical relationship is: -1 'perl' and 'Perl' are not lexically equal. 'perl' is lexically after 'Perl'. 'perl' is not lexically before 'Perl'. The lexical relationship is: 1 The case-insensitive lexical relationship is: 0
Perl 6
Perl 6 uses strong typing dynamically (and gradual typing statically), but normal string and numeric comparisons are coercive. (You may use generic comparison operators if you want polymorphic comparison—but usually you don't. :)
String comparisons never do case folding because that's a very complicated subject in the modern world of Unicode. (You can explicitly apply an appropriate case-folding function to the arguments before doing the comparison, or for "equality" testing you can do matching with a case-insensitive regex, assuming Unicode's language-neutral case-folding rules are okay.) <lang perl6>sub compare($a,$b) {
my $A = "{$a.WHAT.^name} '$a'"; my $B = "{$b.WHAT.^name} '$b'";
if $a eq $b { say "$A and $B are lexically equal" } if $a ne $b { say "$A and $B are not lexically equal" }
if $a gt $b { say "$A is lexically after $B" } if $a lt $b { say "$A is lexically before than $B" }
if $a ge $b { say "$A is not lexically before $B" } if $a le $b { say "$A is not lexically after $B" }
if $a === $b { say "$A and $B are identical objects" } if $a !=== $b { say "$A and $B are not identical objects" }
if $a eqv $b { say "$A and $B are generically equal" } if $a !eqv $b { say "$A and $B are not generically equal" }
if $a before $b { say "$A is generically after $B" } if $a after $b { say "$A is generically before $B" }
if $a !after $b { say "$A is not generically before $B" } if $a !before $b { say "$A is not generically after $B" }
say "The lexical relationship of $A and $B is { $a leg $b }" if $a ~~ Stringy; say "The generic relationship of $A and $B is { $a cmp $b }"; say "The numeric relationship of $A and $B is { $a <=> $b }" if $a ~~ Numeric; say ;
}
compare 'YUP', 'YUP'; compare 'BALL', 'BELL'; compare 24, 123; compare 5.1, 5; compare 5.1e0, 5 + 1/10;</lang>
- Output:
Str 'YUP' and Str 'YUP' are lexically equal Str 'YUP' is not lexically before Str 'YUP' Str 'YUP' is not lexically after Str 'YUP' Str 'YUP' and Str 'YUP' are identical objects Str 'YUP' and Str 'YUP' are generically equal Str 'YUP' is not generically before Str 'YUP' Str 'YUP' is not generically after Str 'YUP' The lexical relationship of Str 'YUP' and Str 'YUP' is Same The generic relationship of Str 'YUP' and Str 'YUP' is Same Str 'BALL' and Str 'BELL' are not lexically equal Str 'BALL' is lexically before than Str 'BELL' Str 'BALL' is not lexically after Str 'BELL' Str 'BALL' and Str 'BELL' are not identical objects Str 'BALL' and Str 'BELL' are not generically equal Str 'BALL' is generically after Str 'BELL' Str 'BALL' is not generically before Str 'BELL' The lexical relationship of Str 'BALL' and Str 'BELL' is Increase The generic relationship of Str 'BALL' and Str 'BELL' is Increase Int '24' and Int '123' are not lexically equal Int '24' is lexically after Int '123' Int '24' is not lexically before Int '123' Int '24' and Int '123' are not identical objects Int '24' and Int '123' are not generically equal Int '24' is generically after Int '123' Int '24' is not generically before Int '123' The generic relationship of Int '24' and Int '123' is Increase The numeric relationship of Int '24' and Int '123' is Increase Rat '5.1' and Int '5' are not lexically equal Rat '5.1' is lexically after Int '5' Rat '5.1' is not lexically before Int '5' Rat '5.1' and Int '5' are not identical objects Rat '5.1' and Int '5' are not generically equal Rat '5.1' is generically before Int '5' Rat '5.1' is not generically after Int '5' The generic relationship of Rat '5.1' and Int '5' is Decrease The numeric relationship of Rat '5.1' and Int '5' is Decrease Num '5.1' and Rat '5.1' are lexically equal Num '5.1' is not lexically before Rat '5.1' Num '5.1' is not lexically after Rat '5.1' Num '5.1' and Rat '5.1' are not identical objects Num '5.1' and Rat '5.1' are not generically equal Num '5.1' is not generically before Rat '5.1' Num '5.1' is not generically after Rat '5.1' The generic relationship of Num '5.1' and Rat '5.1' is Same The numeric relationship of Num '5.1' and Rat '5.1' is Same
PicoLisp
<lang PicoLisp>(setq
str= = str< < str> > )
(println
(str= (lowc "Foo") (lowc "foo") (lowc "fOO")) (str= "f" "foo") (str= "foo" "foo" "foo") (str= "" "") )
(println
(str< "abc" "def") (str> "abc" "def") (str< "" "") (str< "12" "45") )
(bye)</lang>
Python
Notes:
- Python is strongly typed. The string '24' is never coerced to a number, (or vice versa).
- Python does not have case-insensitive string comparison operators, instead use
name.upper()
orname.lower()
to coerce strings to the same case and compare the results.
<lang python>def compare(a, b):
print("\n%r is of type %r and %r is of type %r" % (a, type(a), b, type(b))) if a < b: print('%r is strictly less than %r' % (a, b)) if a <= b: print('%r is less than or equal to %r' % (a, b)) if a > b: print('%r is strictly greater than %r' % (a, b)) if a >= b: print('%r is greater than or equal to %r' % (a, b)) if a == b: print('%r is equal to %r' % (a, b)) if a != b: print('%r is not equal to %r' % (a, b)) if a is b: print('%r has object identity with %r' % (a, b)) if a is not b: print('%r has negated object identity with %r' % (a, b))
compare('YUP', 'YUP') compare('BALL', 'BELL') compare('24', '123') compare(24, 123) compare(5.0, 5)</lang>
- Output:
'YUP' is of type <class 'str'> and 'YUP' is of type <class 'str'> 'YUP' is less than or equal to 'YUP' 'YUP' is greater than or equal to 'YUP' 'YUP' is equal to 'YUP' 'YUP' has object identity with 'YUP' 'BALL' is of type <class 'str'> and 'BELL' is of type <class 'str'> 'BALL' is strictly less than 'BELL' 'BALL' is less than or equal to 'BELL' 'BALL' is not equal to 'BELL' 'BALL' has negated object identity with 'BELL' '24' is of type <class 'str'> and '123' is of type <class 'str'> '24' is strictly greater than '123' '24' is greater than or equal to '123' '24' is not equal to '123' '24' has negated object identity with '123' 24 is of type <class 'int'> and 123 is of type <class 'int'> 24 is strictly less than 123 24 is less than or equal to 123 24 is not equal to 123 24 has negated object identity with 123 5.0 is of type <class 'float'> and 5 is of type <class 'int'> 5.0 is less than or equal to 5 5.0 is greater than or equal to 5 5.0 is equal to 5 5.0 has negated object identity with 5
R
<lang rsplus>compare <- function(a, b) {
cat(paste(a, "is of type", class(a), "and", b, "is of type", class(b), "\n")) if (a < b) cat(paste(a, "is strictly less than", b, "\n")) if (a <= b) cat(paste(a, "is less than or equal to", b, "\n")) if (a > b) cat(paste(a, "is strictly greater than", b, "\n")) if (a >= b) cat(paste(a, "is greater than or equal to", b, "\n")) if (a == b) cat(paste(a, "is equal to", b, "\n")) if (a != b) cat(paste(a, "is not equal to", b, "\n")) invisible()
}
compare('YUP', 'YUP') compare('BALL', 'BELL') compare('24', '123') compare(24, 123) compare(5.0, 5)</lang>
- Output:
1> compare('YUP', 'YUP') YUP is of type character and YUP is of type character YUP is less than or equal to YUP YUP is greater than or equal to YUP YUP is equal to YUP 1> compare('BALL', 'BELL') BALL is of type character and BELL is of type character BALL is strictly less than BELL BALL is less than or equal to BELL BALL is not equal to BELL 1> compare('24', '123') 24 is of type character and 123 is of type character 24 is strictly greater than 123 24 is greater than or equal to 123 24 is not equal to 123 1> compare(24, 123) 24 is of type numeric and 123 is of type numeric 24 is strictly less than 123 24 is less than or equal to 123 24 is not equal to 123 1> compare(5.0, 5) 5 is of type numeric and 5 is of type numeric 5 is less than or equal to 5 5 is greater than or equal to 5 5 is equal to 5
And a more ridiculous version: <lang rsplus>compare <- function(a, b) {
cat(paste(a, "is of type", class(a), "and", b, "is of type", class(b), "\n")) printer <- function(a, b, msg) cat(paste(a, msg, b, "\n")) op <- c(`<`, `<=`, `>`, `>=`, `==`, `!=`) msgs <- c( "is strictly less than", "is less than or equal to", "is strictly greater than", "is greater than or equal to", "is equal to", "is not equal to" ) sapply(1:length(msgs), function(i) if(opi(a, b)) printer(a, b, msgs[i])) invisible()
}</lang>
Racket
<lang racket>
- lang racket
- Comparing two strings for exact equality
(string=? "foo" "foo")
- Comparing two strings for inequality
(not (string=? "foo" "bar"))
- Comparing two strings to see if one is lexically ordered before than the other
(string<? "abc" "def")
- Comparing two strings to see if one is lexically ordered after than the other
(string>? "def" "abc")
- How to achieve both case sensitive comparisons and case insensitive comparisons within the language
(string-ci=? "foo" "FOO") </lang>
REXX
version 1
Note that Dog may or may not be higher than cat, depending upon the underlying hardware
(the order of lowercase and uppercase isn't defined by the REXX language, but rather on how the
characters are represented).
In ASCII, uppercase letters are lower than lowercase, and
in EBCDIC, uppercase letters are higher than lowercase.
Here is a list of some of the strict comparative operators and their meaning:
- == Strictly Equal To
- << Strictly Less Than
- >> Strictly Greater Than
- <<= Strictly Less Than or Equal To
- >>= Strictly Greater Than or Equal To
- \<< Strictly Not Less Than
- \>> Strictly Not Greater Than
Note that some REXXes can use (support) characters other than a backslash [\] for a logical not [¬].
Still other REXX support the use of a tilde [~] for a logical not.
<lang rexx>/*REXX program shows different ways to compare two character strings.*/
say 'This is an ' word('ASCII EBCDIC', 1+(1=='f1')) ' system.'
say
cat = 'cat' animal = 'dog'
if animal = cat then say $(animal) "is lexically equal to" $(cat) if animal \= cat then say $(animal) "is not lexically equal to" $(cat) if animal > cat then say $(animal) "is lexically higher than" $(cat) if animal < cat then say $(animal) "is lexically lower than" $(cat) if animal > cat then say $(animal) "is not lexically lower than" $(cat) if animal < cat then say $(animal) "is not lexically higher than" $(cat)
/*──── [↑] The above comparative operators don't */ /*────consider any leading and/or trailing white- */ /*────space when making comparisons, but the case */ /*────is honored (uppercase, lowercase). */
fatcat=' cat ' /*pad the cat with leading and trailing blanks. */ if fatcat = cat then say $(fatcat) " is equal to" $(cat)
/*────To consider any whitespace in a comparison, */ /*────we need to use strict comparative operators.*/
if fatcat == cat then say $(fatcat) "is strictly equal to" $(cat)
/*────To perform caseless comparisons, the easiest*/ /*────method would be to uppercase a copy of both */ /*────operands. Uppercasing is only done for the */ /*────Latin (or Roman) alphabet in REXX. [↓] */
kat='cAt' if caselessComp(cat,kat) then say $(cat) 'and' $(kat) "are equal caseless" exit /*stick a fork in it, we're done.*/ /*──────────────────────────────────$ subroutine────────────────────────*/ $: return '──►'arg(1)'◄──' /*bracket the string with ──►α◄──*/ /*──────────────────────────────────CASELESSCOMP subroutine─────────────*/ caselessComp: procedure; arg a,b /*ARG uppercases the A & B args.*/
return a==b /*if exactly equal, return 1. */
</lang> Programming note:
If the caselessComp subroutine (above) didn't care about superfluous leading and/or trailing blanks,
the following REXX statement could've be used:
- return a=b
where REXX will then ignore any leading and/or trailing blanks in comparing the a and b strings.
This is equivalent to:
- return strip(a)==strip(b)
output (when executed on an ASCII system):
This is an ASCII system. ──►dog◄── is not lexically equal to ──►cat◄── ──►dog◄── is lexically higher than ──►cat◄── ──►dog◄── is not lexically lower than ──►cat◄── ──► cat ◄── is equal to ──►cat◄── ──►cat◄── and ──►cAt◄── are equal caseless
version 2 (additional aspects)
(a) if both operands are NUMBERS (normal, non-strict) comparisons will always be done arithmetically.
(b) to implement caseless comparison one can proceed as follows:
<lang rexx>/* REXX ***************************************************************
- 16.05.2013 Walter Pachl
- /
Call test 'A','<','a' Call test 'A','=',' a' Call test 'A','==',' a' Call test 'Walter','<',' Wolter' Exit
test: Procedure Parse Arg o1,op,o2 Say q(o1) op q(o2) '->' clcompare(o1,op,o2) Return
clcompare: Procedure /* caseless comparison of the operands */ Parse Arg opd1,op,opd2 opd1u=translate(opd1) opd2u=translate(opd2) Interpret 'res=opd1u' op 'opd2u' Return res
q: Return '"'arg(1)'"'</lang> Output:
"A" < "a" -> 0 "A" = " a" -> 1 "A" == " a" -> 0 "Walter" < " Wolter" -> 1
Ruby
<lang ruby>method_names = [:==,:!=, :>, :>=, :<, :<=, :<=>, :casecmp] [["YUP", "YUP"], ["YUP", "Yup"], ["bot","bat"], ["aaa", "zz"]].each do |str1, str2|
method_names.each{|m| puts "%s %s %s\t%s" % [str1, m, str2, str1.send(m, str2)]} puts
end</lang>
- Output:
YUP == YUP true YUP != YUP false YUP > YUP false YUP >= YUP true YUP < YUP false YUP <= YUP true YUP <=> YUP 0 YUP casecmp YUP 0 YUP == Yup false YUP != Yup true YUP > Yup false YUP >= Yup false YUP < Yup true YUP <= Yup true YUP <=> Yup -1 YUP casecmp Yup 0 bot == bat false bot != bat true bot > bat true bot >= bat true bot < bat false bot <= bat false bot <=> bat 1 bot casecmp bat 1 aaa == zz false aaa != zz true aaa > zz false aaa >= zz false aaa < zz true aaa <= zz true aaa <=> zz -1 aaa casecmp zz -1
Run BASIC
<lang runbasic>a$ = "dog" b$ = "cat" if a$ = b$ then print "the strings are equal" ' test for equalitY if a$ <> b$ then print "the strings are not equal" ' test for inequalitY if a$ > b$ then print a$;" is lexicallY higher than ";b$ ' test for lexicallY higher if a$ < b$ then print a$;" is lexicallY lower than ";b$ ' test for lexicallY lower if a$ <= b$ then print a$;" is not lexicallY higher than ";b$ if a$ >= b$ then print a$;" is not lexicallY lower than ";b$ end</lang>
Scala
<lang Scala>object Compare extends App {
def compare(a: String, b: String) { if (a == b) println(s"'$a' and '$b' are lexically equal.") else println(s"'$a' and '$b' are not lexically equal.")
if (a.equalsIgnoreCase(b)) println(s"'$a' and '$b' are case-insensitive lexically equal.") else println(s"'$a' and '$b' are not case-insensitive lexically equal.")
if (a.compareTo(b) < 0) println(s"'$a' is lexically before '$b'.") else if (a.compareTo(b) > 0) println(s"'$a' is lexically after '$b'.")
if (a.compareTo(b) >= 0) println(s"'$a' is not lexically before '$b'.") if (a.compareTo(b) <= 0) println(s"'$a' is not lexically after '$b'.")
println(s"The lexical relationship is: ${a.compareTo(b)}") println(s"The case-insensitive lexical relationship is: ${a.compareToIgnoreCase(b)}\n") }
compare("Hello", "Hello") compare("5", "5.0") compare("java", "Java") compare("ĴÃVÁ", "ĴÃVÁ") compare("ĴÃVÁ", "ĵãvá")
}</lang>
- Output:
'Hello' and 'Hello' are lexically equal. 'Hello' and 'Hello' are case-insensitive lexically equal. 'Hello' is not lexically before 'Hello'. 'Hello' is not lexically after 'Hello'. The lexical relationship is: 0 The case-insensitive lexical relationship is: 0 '5' and '5.0' are not lexically equal. '5' and '5.0' are not case-insensitive lexically equal. '5' is lexically before '5.0'. '5' is not lexically after '5.0'. The lexical relationship is: -2 The case-insensitive lexical relationship is: -2 'java' and 'Java' are not lexically equal. 'java' and 'Java' are case-insensitive lexically equal. 'java' is lexically after 'Java'. 'java' is not lexically before 'Java'. The lexical relationship is: 32 The case-insensitive lexical relationship is: 0 'ĴÃVÁ' and 'ĴÃVÁ' are lexically equal. 'ĴÃVÁ' and 'ĴÃVÁ' are case-insensitive lexically equal. 'ĴÃVÁ' is not lexically before 'ĴÃVÁ'. 'ĴÃVÁ' is not lexically after 'ĴÃVÁ'. The lexical relationship is: 0 The case-insensitive lexical relationship is: 0 'ĴÃVÁ' and 'ĵãvá' are not lexically equal. 'ĴÃVÁ' and 'ĵãvá' are case-insensitive lexically equal. 'ĴÃVÁ' is lexically before 'ĵãvá'. 'ĴÃVÁ' is not lexically after 'ĵãvá'. The lexical relationship is: -1 The case-insensitive lexical relationship is: 0
Scheme
<lang scheme>
- Comparing two strings for exact equality
(string=? "hello" "hello")
- Comparing two strings for inequality
(not (string=? "hello" "Hello"))
- Checking if the first string is lexically ordered before the second
(string<? "bar" "foo")
- Checking if the first string is lexically ordered after the second
(string>? "foo" "bar")
- case insensitive comparison
(string-ci=? "hello" "Hello")</lang>
Seed7
Seed7 uses the string comparison operators =, <>, <, >, <= and >=. The function compare returns -1, 0 or 1 if the first argument is considered to be respectively less than, equal to, or greater than the second. All string comparisons work case sensitive. The functions upper and lower can be used to do an insensitive comparison.
<lang seed7>$ include "seed7_05.s7i";
const proc: showComparisons (in string: a, in string: b) is func
begin writeln("compare " <& literal(a) <& " with " <& literal(b) <&":"); writeln("a = b returns: " <& a = b); writeln("a <> b returns: " <& a <> b); writeln("a < b returns: " <& a < b); writeln("a > b returns: " <& a > b); writeln("a <= b returns: " <& a <= b); writeln("a >= b returns: " <& a >= b); writeln("compare(a, b) returns: " <& compare(a, b)); writeln("compare(lower(a), lower(b)) returns: " <& compare(a, b)); end func;
const proc: main is func
begin showComparisons("this", "that"); showComparisons("that", "this"); showComparisons("THAT", "That"); showComparisons("this", "This"); showComparisons("this", "this"); showComparisons("the", "there"); showComparisons("there", "the"); end func;</lang>
The function below compares strings, which may contain digit sequences. The digit sequences are compared numerically.
<lang seed7>include "scanstri.s7i";
const func integer: cmpNumeric (in var string: stri1, in var string: stri2) is func
result var integer: signumValue is 0; local var string: part1 is ""; var string: part2 is ""; begin while signumValue = 0 and (stri1 <> "" or stri2 <> "") do part1 := getDigits(stri1); part2 := getDigits(stri2); if part1 <> "" and part2 <> "" then signumValue := compare(part1 lpad0 length(part2), part2 lpad0 length(part1)); if signumValue = 0 then signumValue := compare(length(part1), length(part2)); end if; elsif part1 <> "" then signumValue := compare(part1, stri2); elsif part2 <> "" then signumValue := compare(stri1, part2); end if; if signumValue = 0 then part1 := getNonDigits(stri1); part2 := getNonDigits(stri2); if part1 <> "" and part2 <> "" then signumValue := compare(part1, part2); elsif part1 <> "" then signumValue := compare(part1, stri2); elsif part2 <> "" then signumValue := compare(stri1, part2); end if; end if; end while; end func;</lang>
Original source: [2]
Swift
<lang swift>func compare (a: String, b: String) {
if a == b { println("'\(a)' and '\(b)' are lexically equal.") } if a != b { println("'\(a)' and '\(b)' are not lexically equal.") } if a < b { println("'\(a)' is lexically before '\(b)'.") } if a > b { println("'\(a)' is lexically after '\(b)'.") } if a >= b { println("'\(a)' is not lexically before '\(b)'.") } if a <= b { println("'\(a)' is not lexically after '\(b)'.") }
} compare("cat", "dog")</lang>
- Output:
'cat' and 'dog' are not lexically equal. 'cat' is lexically before 'dog'. 'cat' is not lexically after 'dog'.
Tcl
The best way to compare two strings in Tcl for equality is with the eq
and ne
expression operators:
<lang tcl>if {$a eq $b} {
puts "the strings are equal"
} if {$a ne $b} {
puts "the strings are not equal"
}</lang>
The numeric ==
and !=
operators also mostly work, but can give somewhat unexpected results when the both the values look numeric. The string equal
command is equally suited to equality-testing (and generates the same bytecode).
For ordering, the <
and >
operators may be used, but again they are principally numeric operators. For guaranteed string ordering, the result of the string compare
command should be used instead (which uses the unicode codepoints of the string):
<lang tcl>if {[string compare $a $b] < 0} {
puts "first string lower than second"
} if {[string compare $a $b] > 0} {
puts "first string higher than second"
}</lang>
Greater-or-equal and less-or-equal operations can be done by changing what exact comparison is used on the result of the string compare
.
Tcl also can do a prefix-equal (approximately the same as strncmp()
in C) through the use of the -length option:
<lang tcl>if {[string equal -length 3 $x "abc123"]} {
puts "first three characters are equal"
}</lang>
And case-insensitive equality is (orthogonally) enabled through the -nocase option. These options are supported by both string equal
and string compare
, but not by the expression operators.
UNIX Shell
Traditional bourne shell (which used the 'test' command for comparisons) had no way of doing lexical comparisons.
<lang sh>#!/bin/sh
A=Bell B=Ball
- Traditional test command implementations test for equality and inequality
- but do not have a lexical comparison facility
if [ $A = $B ] ; then
echo 'The strings are equal'
fi if [ $A != $B ] ; then
echo 'The strings are not equal'
fi
- All variables in the shell are strings, so numeric content cause no lexical problems
- 0 , -0 , 0.0 and 00 are all lexically different if tested using the above methods.
- However this may not be the case if other tools, such as awk are the slave instead of test.</lang>
Bash and other POSIX shells do support lexical comparisons:
<lang bash>
- !/bin/bash
isint() {
printf "%d" $1 >/dev/null 2>&1
}
compare() {
local a=$1 local b=$2
$a = $b && echo "'$a' and '$b' are lexically equal" $a != $b && echo "'$a' and '$b' are not lexically equal"
[[ $a > $b ]] && echo "'$a' is lexically after '$b'" [[ $a < $b ]] && echo "'$a' is lexically before '$b'"
shopt -s nocasematch # Turn on case insensitivity
$a = $b && echo "'$a' and '$b' are equal with case insensitivity"
shopt -u nocasematch # Turn off case insensitivity
# If args are numeric, perform some numeric comparisions if isint $a && isint $b then $a -eq $b && echo "$a is numerically equal to $b" $a -gt $b && echo "$a is numerically greater than $b" $a -lt $b && echo "$a is numerically less than $b" fi
echo
}
compare foo foo
compare foo bar
compare FOO foo
compare 24 123
compare 50 20
</lang>
- Output:
'foo' and 'foo' are lexically equal 'foo' and 'foo' are equal with case insensitivity 'foo' and 'bar' are not lexically equal 'foo' is lexically after 'bar' 'FOO' and 'foo' are not lexically equal 'FOO' is lexically before 'foo' 'FOO' and 'foo' are equal with case insensitivity '24' and '123' are not lexically equal '24' is lexically after '123' 24 is numerically less than 123 '50' and '20' are not lexically equal '50' is lexically after '20' 50 is numerically greater than 20
zkl
<lang zkl>"foo" == "foo" //True "foo" == "FOO" //False "foo" == "foobar" //False Op("==")("foo","foo") //True Op("==","foo")("foo") //True
"abc"<"cde" //True "abc">"cde" //False
"foo" == "FOO" //False "abc".toUpper()=="ABC" //True
123=="123" //False 123=="123".toInt() //True
123<"123" //False, int on left forces "123".toInt() 123<"1234" //True 2345<"1234" //False</lang>
- Programming Tasks
- Basic Data Operations
- Basic language learning
- Simple
- Ada
- Aime
- AWK
- BASIC
- Applesoft BASIC
- Bracmat
- Burlesque
- C
- Clipper
- COBOL
- Common Lisp
- Component Pascal
- D
- Erlang
- F Sharp
- Forth
- Go
- Harbour
- Haskell
- Icon
- Unicon
- J
- Java
- Jq
- Lasso
- Lua
- Mathematica
- NetRexx
- Nim
- Oforth
- OoRexx
- PARI/GP
- Perl
- Perl 6
- PicoLisp
- Python
- R
- Racket
- REXX
- Ruby
- Run BASIC
- Scala
- Scheme
- Seed7
- Swift
- Tcl
- UNIX Shell
- Zkl
- Bc/Omit
- Brlcad/Omit
- Dc/Omit
- GUISS/Omit
- Lilypond/Omit
- Openscad/Omit