String comparison
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
- Task
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 Raku entry for an example of a language with both kinds of operators.
- Metrics
- Counting
- Word frequency
- Letter frequency
- Jewels and stones
- I before E except after C
- Bioinformatics/base count
- Count occurrences of a substring
- Count how many vowels and consonants occur in a string
- Remove/replace
- XXXX redacted
- Conjugate a Latin verb
- Remove vowels from a string
- String interpolation (included)
- Strip block comments
- Strip comments from a string
- Strip a set of characters from a string
- Strip whitespace from a string -- top and tail
- Strip control codes and extended characters from a string
- Anagrams/Derangements/shuffling
- Word wheel
- ABC problem
- Sattolo cycle
- Knuth shuffle
- Ordered words
- Superpermutation minimisation
- Textonyms (using a phone text pad)
- Anagrams
- Anagrams/Deranged anagrams
- Permutations/Derangements
- Find/Search/Determine
- ABC words
- Odd words
- Word ladder
- Semordnilap
- Word search
- Wordiff (game)
- String matching
- Tea cup rim text
- Alternade words
- Changeable words
- State name puzzle
- String comparison
- Unique characters
- Unique characters in each string
- Extract file extension
- Levenshtein distance
- Palindrome detection
- Common list elements
- Longest common suffix
- Longest common prefix
- Compare a list of strings
- Longest common substring
- Find common directory path
- Words from neighbour ones
- Change e letters to i in words
- Non-continuous subsequences
- Longest common subsequence
- Longest palindromic substrings
- Longest increasing subsequence
- Words containing "the" substring
- Sum of the digits of n is substring of n
- Determine if a string is numeric
- Determine if a string is collapsible
- Determine if a string is squeezable
- Determine if a string has all unique characters
- Determine if a string has all the same characters
- Longest substrings without repeating characters
- Find words which contains all the vowels
- Find words which contain the most consonants
- Find words which contains more than 3 vowels
- Find words whose first and last three letters are equal
- Find words with alternating vowels and consonants
- Formatting
- Substring
- Rep-string
- Word wrap
- String case
- Align columns
- Literals/String
- Repeat a string
- Brace expansion
- Brace expansion using ranges
- Reverse a string
- Phrase reversals
- Comma quibbling
- Special characters
- String concatenation
- Substring/Top and tail
- Commatizing numbers
- Reverse words in a string
- Suffixation of decimal numbers
- Long literals, with continuations
- Numerical and alphabetical suffixes
- Abbreviations, easy
- Abbreviations, simple
- Abbreviations, automatic
- Song lyrics/poems/Mad Libs/phrases
- Mad Libs
- Magic 8-ball
- 99 bottles of beer
- The Name Game (a song)
- The Old lady swallowed a fly
- The Twelve Days of Christmas
- Tokenize
- Text between
- Tokenize a string
- Word break problem
- Tokenize a string with escaping
- Split a character string based on change of character
- Sequences
11l
Note: 11l does not have case-insensitive string comparison operators, instead use name.upper()
or name.lower()
to coerce strings to the same case and compare the results.
F compare(a, b)
I a < b {print(‘'#.' is strictly less than '#.'’.format(a, b))}
I a <= b {print(‘'#.' is less than or equal to '#.'’.format(a, b))}
I a > b {print(‘'#.' is strictly greater than '#.'’.format(a, b))}
I a >= b {print(‘'#.' is greater than or equal to '#.'’.format(a, b))}
I a == b {print(‘'#.' is equal to '#.'’.format(a, b))}
I a != b {print(‘'#.' is not equal to '#.'’.format(a, b))}
compare(‘YUP’, ‘YUP’)
compare(‘BALL’, ‘BELL’)
compare(‘24’, ‘123’)
- Output:
'YUP' is less than or equal to 'YUP' 'YUP' is greater than or equal to 'YUP' 'YUP' is equal to 'YUP' 'BALL' is strictly less than 'BELL' 'BALL' is less than or equal to 'BELL' 'BALL' is not equal to 'BELL' '24' is strictly greater than '123' '24' is greater than or equal to '123' '24' is not equal to '123'
AArch64 Assembly
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program comparString64.s */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
/*******************************************/
/* Initialized data */
/*******************************************/
.data
szMessStringEqu: .asciz "The strings are equals.\n"
szMessStringNotEqu: .asciz "The strings are not equals.\n"
szCarriageReturn: .asciz "\n"
szString1: .asciz "ABCDE"
szString2: .asciz "ABCDE"
szString3: .asciz "ABCFG"
szString4: .asciz "ABC"
szString5: .asciz "abcde"
/*******************************************/
/* UnInitialized data /
/*******************************************/
.bss
/*******************************************/
/* code section */
/*******************************************/
.text
.global main
main: // entry of program
ldr x0,qAdrszString1
ldr x1,qAdrszString2
bl Comparaison
ldr x0,qAdrszString1
ldr x1,qAdrszString3
bl Comparaison
ldr x0,qAdrszString1
ldr x1,qAdrszString4
bl Comparaison
// case sensitive comparisons ABCDE et abcde
ldr x0,qAdrszString1
ldr x1,qAdrszString5
bl Comparaison
// case insensitive comparisons ABCDE et abcde
ldr x0,qAdrszString1
ldr x1,qAdrszString5
bl comparStringsInsensitive
cbnz x0,1f
ldr x0,qAdrszMessStringEqu
bl affichageMess
b 2f
1:
ldr x0,qAdrszMessStringNotEqu
bl affichageMess
2:
100: // standard end of the program
mov x0,0 // return code
mov x8,EXIT // request to exit program
svc 0 // perform the system call
qAdrszString1: .quad szString1
qAdrszString2: .quad szString2
qAdrszString3: .quad szString3
qAdrszString4: .quad szString4
qAdrszString5: .quad szString5
qAdrszMessStringEqu: .quad szMessStringEqu
qAdrszMessStringNotEqu: .quad szMessStringNotEqu
qAdrszCarriageReturn: .quad szCarriageReturn
/*********************************************/
/* comparaison */
/*********************************************/
/* x0 contains address String 1 */
/* x1 contains address String 2 */
Comparaison:
stp x1,lr,[sp,-16]! // save registers
bl comparStrings
cbnz x0,1f
ldr x0,qAdrszMessStringEqu
bl affichageMess
b 2f
1:
ldr x0,qAdrszMessStringNotEqu
bl affichageMess
2:
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/************************************/
/* Strings case sensitive comparisons */
/************************************/
/* x0 et x1 contains the address of strings */
/* return 0 in x0 if equals */
/* return -1 if string x0 < string x1 */
/* return 1 if string x0 > string x1 */
comparStrings:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
mov x2,#0 // counter
1:
ldrb w3,[x0,x2] // byte string 1
ldrb w4,[x1,x2] // byte string 2
cmp x3,x4
blt 2f
bgt 3f
cbz x3,4f // 0 end string
add x2,x2,1 // else add 1 in counter
b 1b // and loop */
2:
mov x0,-1 // lower
b 100f
3:
mov x0,1 // higher
b 100f
4:
mov x0,0 // equal
100:
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/************************************/
/* Strings case insensitive comparisons */
/************************************/
/* x0 et x1 contains the address of strings */
/* return 0 in x0 if equals */
/* return -1 if string x0 < string x1 */
/* return 1 if string x0 > string x1 */
comparStringsInsensitive:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
mov x2,#0 // counter
1:
ldrb w3,[x0,x2] // byte string 1
ldrb w4,[x1,x2] // byte string 2
// majuscules --> minuscules byte 1
cmp x3,65
blt 2f
cmp x3,90
bgt 2f
add x3,x3,32
2: // majuscules --> minuscules byte 2
cmp x4,65
blt 3f
cmp x4,90
bgt 3f
add x4,x4,32
3:
cmp x3,x4
blt 4f
bgt 5f
cbz x3,6f // 0 end string
add x2,x2,1 // else add 1 in counter
b 1b // and loop
4:
mov x0,-1 // lower
b 100f
5:
mov x0,1 // higher
b 100f
6:
mov x0,0 // equal
100:
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
Action!
PROC TestEqual(CHAR ARRAY s1,s2)
INT res
PrintF("""%S"" and ""%S"" are equal: ",s1,s2)
IF SCompare(s1,s2)=0 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestInequal(CHAR ARRAY s1,s2)
INT res
PrintF("""%S"" and ""%S"" are inequal: ",s1,s2)
IF SCompare(s1,s2)#0 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestBefore(CHAR ARRAY s1,s2)
INT res
PrintF("""%S"" is before ""%S"": ",s1,s2)
IF SCompare(s1,s2)<0 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestAfter(CHAR ARRAY s1,s2)
INT res
PrintF("""%S"" is after ""%S"": ",s1,s2)
IF SCompare(s1,s2)>0 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestNumEqual(CHAR ARRAY s1,s2)
INT v1,v2
PrintF("""%S"" and ""%S"" are equal: ",s1,s2)
v1=ValI(s1) v2=ValI(s2)
IF v1=v2 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestNumInequal(CHAR ARRAY s1,s2)
INT v1,v2
PrintF("""%S"" and ""%S"" are inequal: ",s1,s2)
v1=ValI(s1) v2=ValI(s2)
IF v1#v2 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestNumBefore(CHAR ARRAY s1,s2)
INT v1,v2
PrintF("""%S"" is before ""%S"": ",s1,s2)
v1=ValI(s1) v2=ValI(s2)
IF v1<v2 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC TestNumAfter(CHAR ARRAY s1,s2)
INT v1,v2
PrintF("""%S"" is after ""%S"": ",s1,s2)
v1=ValI(s1) v2=ValI(s2)
IF v1>v2 THEN
PrintE("True")
ELSE
PrintE("False")
FI
RETURN
PROC Main()
PrintE("Lexical comparison:")
TestEqual("abcd","Abcd")
TestInequal("abcd","Abcd")
TestBefore("abcd","Abcd")
TestAfter("abcd","Abcd")
PutE()
PrintE("Numerical comparison:")
TestNumEqual("1234","99876")
TestNumInequal("1234","99876")
TestNumBefore("1234","99876")
TestNumAfter("1234","99876")
RETURN
- Output:
Screenshot from Atari 8-bit computer
Lexical comparison: "abcd" and "Abcd" are equal: False "abcd" and "Abcd" are inequal: True "abcd" is before "Abcd": False "abcd" is after "Abcd": True Numerical comparison: "1234" and "99876" are equal: False "1234" and "99876" are inequal: True "1234" is before "99876": False "1234" is after "99876": True
Ada
Ada uses the usual comparison operators ("=" for equality, "/=" for not being equal, etc.) for strings. One uses the same comparison operators to compare variables of other types (integers, floating point numbers, etc.). 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]]
with Ada.Text_IO, Ada.Strings.Equal_Case_Insensitive;
procedure String_Compare is
procedure Print_Comparison (A, B : String) is
begin
Ada.Text_IO.Put_Line
("""" & A & """ and """ & B & """: " &
(if A = B then
"equal, "
elsif Ada.Strings.Equal_Case_Insensitive (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 <=), ") &
(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;
- 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
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));
- Output:
occidental vs oriental (==, !=, <, <=, >=, >): 0 -15 1 1 0 0 Oriental vs oriental (==, !=, <, >): 0 -32 1 0 Oriental vs oriental (==, !=, <, >): 1 0 0 0
ALGOL 68
STRING sa := "abc ", sb := "ABC ";
# when comparing strings, Algol 68 ignores trailing blanks #
# so e.g. "a" = "a " is true #
# test procedure, prints message if condition is TRUE #
PROC test = ( BOOL condition, STRING message )VOID:
IF condition THEN print( ( message, newline ) ) FI;
# equality? #
test( sa = sb, "sa = sb" );
# inequality? #
test( sa /= sb, "sa not = sb" );
# lexically ordered before? #
test( sa < sb, "sa < sb" );
# lexically ordered after? #
test( sa >s b, "sa > sb" );
# Algol 68's builtin string comparison operators are case-sensitive. #
# To perform case insensitive comparisons, procedures or operators #
# would need to be written #
# e.g. #
# compare two strings, ignoring case #
# Note the "to upper" PROC is an Algol 68G extension #
# It could be written in standard Algol 68 (assuming ASCII) as e.g. #
# PROC to upper = ( CHAR c )CHAR: #
# IF c < "a" OR c > "z" THEN c #
# ELSE REPR ( ( ABS c - ABS "a" ) + ABS "A" ) FI; #
PROC caseless comparison = ( STRING a, b )INT:
BEGIN
INT a max = UPB a, b max = UPB b;
INT a pos := LWB a, b pos := LWB b;
INT result := 0;
WHILE result = 0
AND ( a pos <= a max OR b pos <= b max )
DO
CHAR a char := to upper( IF a pos <= a max THEN a[ a pos ] ELSE " " FI );
CHAR b char := to upper( IF b pos <= b max THEN b[ b pos ] ELSE " " FI );
result := ABS a char - ABS b char;
a pos +:= 1;
b pos +:= 1
OD;
IF result < 0 THEN -1 ELIF result > 0 THEN 1 ELSE 0 FI
END ; # caseless comparison #
# compare two strings for equality, ignoring case #
PROC equal ignoring case = ( STRING a, b )BOOL: caseless comparison( a, b ) = 0;
# similar procedures for inequality and lexical ording ... #
test( equal ignoring case( sa, sb ), "sa = sb (ignoring case)" );
# Algol 68 is strongly typed - strings cannot be compared to e.g. integers #
# unless procedures or operators are written, e.g. #
# e.g. OP = = ( STRING a, INT b )BOOL: a = whole( b, 0 ); #
# OP = = ( INT a, STRING b )BOOL: b = a; #
# etc. #
# Algol 68 also has <= and >= comparison operators for testing for #
# "lexically before or equal" and "lexically after or equal" #
test( sa <= sb, "sa <= sb" );
test( sa >= sb, "sa >= sb" )
# there are no other forms of string comparison builtin to Algol 68 #
- Output:
sa not = sb sa > sb sa = sb (ignoring case) sa >= sb
ALGOL W
begin
string(10) a;
string(12) b;
a := "abc";
b := "ABC";
% when comparing strings, Algol W ignores trailing blanks %
% so e.g. "a" = "a " is true %
% equality? %
if a = b then write( "a = b" );
% inequality? %
if a not = b then write( "a not = b" );
% lexically ordered before? %
if a < b then write( "a < b" );
% lexically ordered after? %
if a > b then write( "a > b" );
% Algol W string comparisons are case-sensitive. To perform case %
% insensitive comparisons, procedures would need to be written %
% e.g. as in the following block (assuming the character set is ASCII) %
begin
% convert a character to upper-case %
integer procedure toupper( integer value c ) ;
if c < decode( "a" ) or c > decode( "z" ) then c
else ( c - decode( "a" ) ) + decode( "A" );
% compare two strings, ignoring case %
% note that strings can be at most 256 characters long in Algol W %
integer procedure caselessComparison ( string(256) value a, b ) ;
begin
integer comparisonResult, pos;
comparisonResult := pos := 0;
while pos < 256 and comparisonResult = 0 do begin
comparisonResult := toupper( decode( a(pos//1) ) )
- toupper( decode( b(pos//1) ) );
pos := pos + 1
end;
if comparisonResult < 0 then -1
else if comparisonResult > 0 then 1
else 0
end caselessComparison ;
% compare two strings for equality, ignoring case %
logical procedure equalIgnoringCase ( string(256) value a, b ) ;
( caselessComparison( a, b ) = 0 );
% similar procedures for inequality and lexical ording ... %
if equalIgnoringCase( a, b ) then write( "a = b (ignoring case)" )
end caselessComparison ;
% Algol W is strongly typed - strings cannot be compared to e.g. integers %
% e.g. "if a = 23 then ..." would be a syntax error %
% Algol W also has <= and >= comparison operators for testing for %
% "lexically before or equal" and "lexically after or equal" %
if a <= b then write( "a <= b" );
if a >= b then write( "a >= b" );
% there are no other forms of string comparison builtin to Algol W %
end.
- Output:
a not = b a > b a = b (ignoring case) a >= b
Apex
Unlike Java, Apex Strings support using the comparison operators ==, !=, <, <=, >, and >=. Comparisons can be done also using the equals(), equalsIgnoreCase() and compareTo() methods.
public class Compare
{
/**
* Test in the developer console:
* Compare.compare('Hello', 'Hello');
* Compare.compare('5', '5.0');
* Compare.compare('java', 'Java');
* Compare.compare('ĴÃVÁ', 'ĴÃVÁ');
*/
public static void compare (String A, String B)
{
if (A.equals(B))
System.debug(A + ' and ' + B + ' are lexically equal.');
else
System.debug(A + ' and ' + B + ' are not lexically equal.');
if (A.equalsIgnoreCase(B))
System.debug(A + ' and ' + B + ' are case-insensitive lexically equal.');
else
System.debug(A + ' and ' + B + ' are not case-insensitive lexically equal.');
if (A.compareTo(B) < 0)
System.debug(A + ' is lexically before ' + B);
else if (A.compareTo(B) > 0)
System.debug(A + ' is lexically after ' + B);
if (A.compareTo(B) >= 0)
System.debug(A + ' is not lexically before ' + B);
if (A.compareTo(B) <= 0)
System.debug(A + ' is not lexically after ' + B);
System.debug('The lexical relationship is: ' + A.compareTo(B));
}
}
- 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 '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 '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 'ĴÃ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
AppleScript
--Comparing two strings for exact equality
set s1 to "this"
set s2 to "that"
if s1 is s2 then
-- strings are equal
end if
--Comparing two strings for inequality (i.e., the inverse of exact equality)
if s1 is not s2 then
-- string are not equal
end if
-- Comparing two strings to see if one is lexically ordered before than the other
if s1 < s2 then
-- s1 is lexically ordered before s2
end if
-- Comparing two strings to see if one is lexically ordered after than the other
if s1 > s2 then
-- s1 is lexically ordered after s2
end if
-- How to achieve both case sensitive comparisons and case insensitive comparisons within the language
set s1 to "this"
set s2 to "This"
considering case
if s1 is s2 then
-- strings are equal with case considering
end if
end considering
ignoring case -- default
if s2 is s2 then
-- string are equal without case considering
end if
end ignoring
-- 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.
-- When comparing the right object is coerced into the same type as the object left from the operator. This implicit coercion enables to compare integers with strings (containining integer values).
set s1 to "3"
set int1 to 2
if s1 < int1 then
-- comparison is lexically
end if
if int1 < s1 then
-- comparison is numeric
end if
ARM Assembly
/* ARM assembly Raspberry PI */
/* program comparString.s */
/* Constantes */
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
/* Initialized data */
.data
szMessStringEqu: .asciz "The strings are equals.\n"
szMessStringNotEqu: .asciz "The strings are not equals.\n"
szCarriageReturn: .asciz "\n"
szString1: .asciz "ABCDE"
szString2: .asciz "ABCDE"
szString3: .asciz "ABCFG"
szString4: .asciz "ABC"
szString5: .asciz "abcde"
/* UnInitialized data */
.bss
/* code section */
.text
.global main
main: /* entry of program */
push {fp,lr} /* saves 2 registers */
ldr r0,iAdrszString1
ldr r1,iAdrszString2
bl Comparaison
ldr r0,iAdrszString1
ldr r1,iAdrszString3
bl Comparaison
ldr r0,iAdrszString1
ldr r1,iAdrszString4
bl Comparaison
@ case sensitive comparisons ABCDE et abcde
ldr r0,iAdrszString1
ldr r1,iAdrszString5
bl Comparaison
@ case insensitive comparisons ABCDE et abcde
ldr r0,iAdrszString1
ldr r1,iAdrszString5
bl comparStringsInsensitive
cmp r0,#0
bne 1f
ldr r0,iAdrszMessStringEqu
bl affichageMess
b 2f
1:
ldr r0,iAdrszMessStringNotEqu
bl affichageMess
2:
100: /* standard end of the program */
mov r0, #0 @ return code
pop {fp,lr} @restaur 2 registers
mov r7, #EXIT @ request to exit program
swi 0 @ perform the system call
iAdrszString1: .int szString1
iAdrszString2: .int szString2
iAdrszString3: .int szString3
iAdrszString4: .int szString4
iAdrszString5: .int szString5
iAdrszMessStringEqu: .int szMessStringEqu
iAdrszMessStringNotEqu: .int szMessStringNotEqu
iAdrszCarriageReturn: .int szCarriageReturn
/*********************************************/
/* comparaison */
/*********************************************/
/* r0 contains address String 1 */
/* r1 contains address String 2 */
Comparaison:
push {fp,lr} /* save registres */
bl comparStrings
cmp r0,#0
bne 1f
ldr r0,iAdrszMessStringEqu
bl affichageMess
b 2f
1:
ldr r0,iAdrszMessStringNotEqu
bl affichageMess
2:
pop {fp,lr} /* restaur des 2 registres */
bx lr /* return */
/******************************************************************/
/* display text with size calculation */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
push {fp,lr} /* save registres */
push {r0,r1,r2,r7} /* save others registers */
mov r2,#0 /* counter length */
1: /* loop length calculation */
ldrb r1,[r0,r2] /* read octet start position + index */
cmp r1,#0 /* if 0 its over */
addne r2,r2,#1 /* else add 1 in the length */
bne 1b /* and loop */
/* so here r2 contains the length of the message */
mov r1,r0 /* address message in r1 */
mov r0,#STDOUT /* code to write to the standard output Linux */
mov r7, #WRITE /* code call system "write" */
swi #0 /* call systeme */
pop {r0,r1,r2,r7} /* restaur others registers */
pop {fp,lr} /* restaur des 2 registres */
bx lr /* return */
/************************************/
/* Strings case sensitive comparisons */
/************************************/
/* r0 et r1 contains the address of strings */
/* return 0 in r0 if equals */
/* return -1 if string r0 < string r1 */
/* return 1 if string r0 > string r1 */
comparStrings:
push {r1-r4} /* save des registres */
mov r2,#0 /* counter */
1:
ldrb r3,[r0,r2] /* byte string 1 */
ldrb r4,[r1,r2] /* byte string 2 */
cmp r3,r4
movlt r0,#-1 /* small */
movgt r0,#1 /* greather */
bne 100f /* not equals */
cmp r3,#0 /* 0 end string */
moveq r0,#0 /* equals */
beq 100f /* end string */
add r2,r2,#1 /* else add 1 in counter */
b 1b /* and loop */
100:
pop {r1-r4}
bx lr
/************************************/
/* Strings case insensitive comparisons */
/************************************/
/* r0 et r1 contains the address of strings */
/* return 0 in r0 if equals */
/* return -1 if string r0 < string r1 */
/* return 1 if string r0 > string r1 */
comparStringsInsensitive:
push {r1-r4} /* save des registres */
mov r2,#0 /* counter */
1:
ldrb r3,[r0,r2] /* byte string 1 */
ldrb r4,[r1,r2] /* byte string 2 */
@ majuscules --> minuscules byte 1
cmp r3,#65
blt 2f
cmp r3,#90
bgt 2f
add r3,#32
2: @ majuscules --> minuscules byte 2
cmp r4,#65
blt 3f
cmp r4,#90
bgt 3f
add r4,#32
3:
cmp r3,r4
movlt r0,#-1 /* small */
movgt r0,#1 /* greather */
bne 100f /* not equals */
cmp r3,#0 /* 0 end string */
moveq r0,#0 /* equal */
beq 100f /* end strings */
add r2,r2,#1 /* else add 1 in counter */
b 1b /* and loop */
100:
pop {r1-r4}
bx lr /* end procedure */
Arturo
loop [["YUP" "YUP"] ["YUP" "Yup"] ["bot" "bat"] ["aaa" "zz"]] 'x [
print [x\0 "=" x\1 "=>" x\0 = x\1]
print [x\0 "=" x\1 "(case-insensitive) =>" (upper x\0) = upper x\1]
print [x\0 "<>" x\1 "=>" x\0 <> x\1]
print [x\0 ">" x\1 "=>" x\0 > x\1]
print [x\0 ">=" x\1 "=>" x\0 >= x\1]
print [x\0 "<" x\1 "=>" x\0 < x\1]
print [x\0 "=<" x\1 "=>" x\0 =< x\1]
print "----"
]
- Output:
YUP = YUP => true YUP = YUP (case-insensitive) => true YUP <> YUP => false YUP > YUP => false YUP >= YUP => true YUP < YUP => false YUP =< YUP => true ---- YUP = Yup => false YUP = Yup (case-insensitive) => true YUP <> Yup => true YUP > Yup => false YUP >= Yup => false YUP < Yup => true YUP =< Yup => true ---- bot = bat => false bot = bat (case-insensitive) => false bot <> bat => true bot > bat => true bot >= bat => true bot < bat => false bot =< bat => false ---- aaa = zz => false aaa = zz (case-insensitive) => false aaa <> zz => true aaa > zz => false aaa >= zz => false aaa < zz => true aaa =< zz => true ----
Astro
fun compare(a, b):
print("\n$a is of type ${typeof(a)} and $b is of type ${typeof(b)}")
if a < b: print("$a is strictly less than $b")
if a <= b: print("$a is less than or equal to $b")
if a > b: print("$a is strictly greater than $b")
if a >= b: print("$a is greater than or equal to $b")
if a == b: print("$a is equal to $b")
if a != b: print("$a is not equal to $b")
if a is b: print("$a has object identity with $b")
if a is not b: print("$a has negated object identity with $b")
compare("YUP", "YUP")
compare('a', 'z')
compare("24", "123")
compare(24, 123)
compare(5.0, 5)
Avail
Method "string comparisons_,_" is
[
a : string,
b : string
|
Print: "a & b are equal? " ++ “a = b”;
Print: "a & b are not equal? " ++ “a ≠ b”;
// Inequalities compare by code point
Print: "a is lexically before b? " ++ “a < b”;
Print: "a is lexically after b? " ++ “a > b”;
// Supports non-strict inequalities
Print: "a is not lexically before b? " ++ “a ≥ b”;
Print: "a is not lexically after b? " ++ “a ≤ b”;
// Case-insensitive comparison requires a manual case conversion
Print: "a & b are equal case-insensitively?" ++ “lowercase a = lowercase b”;
];
Avail is strongly-typed and the standard library's comparison functions do not admit mixed comparison between numerics and strings. Strings are immutable tuples of characters and are always compared by value -- few entities in Avail have identity so "object equality" is usually meaningless.
AutoHotkey
exact_equality(a,b){
return (a==b)
}
exact_inequality(a,b){
return !(a==b)
}
equality(a,b){
return (a=b)
}
inequality(a,b){
return !(a=b)
}
ordered_before(a,b){
return ("" a < "" b)
}
ordered_after(a,b){
return ("" a > "" b)
}
Examples:
for a, b in {"alpha":"beta", "Gamma":"gamma", 100:5}
MsgBox % a " vs " b "`n"
. "exact_equality case sensitive : " exact_equality(a,b) "`n"
. "exact_inequality case sensitive :" exact_inequality(a,b) "`n"
. "equality case insensitive : " equality(a,b) "`n"
. "inequality case insensitive : " inequality(a,b) "`n"
. "ordered_before : " ordered_before(a,b) "`n"
. "ordered_after : " ordered_after(a,b) "`n"
- Output:
100 vs 5 exact_equality case sensitive : 0 exact_inequality case sensitive :1 equality case insensitive : 0 inequality case insensitive : 1 ordered_before : 1 ordered_after : 0 --------------------------- alpha vs beta exact_equality case sensitive : 0 exact_inequality case sensitive :1 equality case insensitive : 0 inequality case insensitive : 1 ordered_before : 1 ordered_after : 0 --------------------------- Gamma vs gamma exact_equality case sensitive : 0 exact_inequality case sensitive :1 equality case insensitive : 1 inequality case insensitive : 0 ordered_before : 0 ordered_after : 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.
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" }
}
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
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.
10 LET A$="BELT"
20 LET B$="belt"
30 IF UPPER$(A$)=UPPER$(B$) THEN PRINT "Disregarding lettercase, the strings are the same."
Applesoft BASIC
For case sensitive comparisons
Applesoft BASIC does not have a built in UPPER$ function.
BASIC256
function StringCompare(s1, s2, ignoreCase)
if ignoreCase then
s = lower(s1)
t = lower(s2)
else
s = s1
t = s2
end if
if s < t then return " comes before "
if s = t then return " is equal to "
return " comes after "
end function
s1 = "Dog" : s2 = "Dog"
print s1; StringCompare(s1, s2, False); s2
s2 = "Cat"
print s1; StringCompare(s1, s2, False); s2
s2 = "Rat"
print s1; StringCompare(s1, s2, False); s2
s2 = "dog"
print s1; StringCompare(s1, s2, False); s2
print s1; StringCompare(s1, s2, True); s2; " if case is ignored"
s1 = "Dog" : s2 = "Pig"
s3 = StringCompare(s1, s2, False)
if s3 <> " is equal to " then print s1; " is not equal to "; s2
end
- Output:
Igual que la entrada de FreeBASIC.
BBC BASIC
REM >strcomp
shav$ = "Shaw, George Bernard"
shakes$ = "Shakespeare, William"
:
REM test equality
IF shav$ = shakes$ THEN PRINT "The two strings are equal" ELSE PRINT "The two strings are not equal"
:
REM test inequality
IF shav$ <> shakes$ THEN PRINT "The two strings are unequal" ELSE PRINT "The two strings are not unequal"
:
REM test lexical ordering
IF shav$ > shakes$ THEN PRINT shav$; " is lexically higher than "; shakes$ ELSE PRINT shav$; " is not lexically higher than "; shakes$
IF shav$ < shakes$ THEN PRINT shav$; " is lexically lower than "; shakes$ ELSE PRINT shav$; " is not lexically lower than "; shakes$
REM the >= and <= operators can also be used, & behave as expected
:
REM string comparison is case-sensitive by default, and BBC BASIC
REM does not provide built-in functions to convert to all upper
REM or all lower case; but it is easy enough to define one
:
IF FN_upper(shav$) = FN_upper(shakes$) THEN PRINT "The two strings are equal (disregarding case)" ELSE PRINT "The two strings are not equal (even disregarding case)"
END
:
DEF FN_upper(s$)
LOCAL i%, ns$
ns$ = ""
FOR i% = 1 TO LEN s$
IF ASC(MID$(s$, i%, 1)) >= ASC "a" AND ASC(MID$(s$, i%, 1)) <= ASC "z" THEN ns$ += CHR$(ASC(MID$(s$, i%, 1)) - &20) ELSE ns$ += MID$(s$, i%, 1)
NEXT
= ns$
- Output:
The two strings are not equal The two strings are unequal Shaw, George Bernard is lexically higher than Shakespeare, William Shaw, George Bernard is not lexically lower than Shakespeare, William The two strings are not equal (even disregarding case)
QBasic
FUNCTION StringCompare$ (s1 AS STRING, s2 AS STRING, ignoreCase)
DIM s AS STRING, t AS STRING
IF ignoreCase THEN
s = LCASE$(s1)
t = LCASE$(s2)
ELSE
s = s1
t = s2
END IF
IF s < t THEN StringCompare$ = " comes before ": EXIT FUNCTION
IF s = t THEN StringCompare$ = " is equal to ": EXIT FUNCTION
StringCompare$ = " comes after "
END FUNCTION
DIM s1 AS STRING, s2 AS STRING, s3 AS STRING
s1 = "Dog": s2 = "Dog"
PRINT s1; StringCompare$(s1, s2, 0); s2
s2 = "Cat"
PRINT s1; StringCompare$(s1, s2, 0); s2
s2 = "Rat"
PRINT s1; StringCompare$(s1, s2, 0); s2
s2 = "dog"
PRINT s1; StringCompare$(s1, s2, 0); s2
PRINT s1; StringCompare$(s1, s2, 1); s2; " if case is ignored"
s1 = "Dog": s2 = "Pig"
s3 = StringCompare$(s1, s2, 0)
IF s3 <> " is equal to " THEN PRINT s1; " is not equal to "; s2
END
- Output:
Igual que la entrada de FreeBASIC.
True BASIC
FUNCTION StringCompare$(s1$, s2$, ignorecase)
IF ignorecase = True then
LET s$ = LCASE$(s1$)
LET t$ = LCASE$(s2$)
ELSE
LET s$ = s1$
LET t$ = s2$
END IF
IF s$ < t$ then
LET StringCompare$ = " comes before "
ELSE
IF s$ = t$ then
LET StringCompare$ = " is equal to "
ELSE
LET StringCompare$ = " comes after "
END IF
END IF
END FUNCTION
LET s1$ = "Dog"
LET s2$ = "Dog"
PRINT s1$; StringCompare$(s1$, s2$, False); s2$
LET s2$ = "Cat"
PRINT s1$; StringCompare$(s1$, s2$, False); s2$
LET s2$ = "Rat"
PRINT s1$; StringCompare$(s1$, s2$, False); s2$
LET s2$ = "dog"
PRINT s1$; StringCompare$(s1$, s2$, False); s2$
PRINT s1$; StringCompare$(s1$, s2$, True); s2$; " if case is ignored"
LET s1$ = "Dog"
LET s2$ = "Pig"
LET s3$ = StringCompare$(s1$, s2$, 0)
IF s3$ <> " is equal to " then PRINT s1$; " is not equal to "; s2$
END
- Output:
Igual que la entrada de FreeBASIC.
Yabasic
sub StringCompare$(s1$, s2$, ignoreCase)
local s$, t$
if ignoreCase then
s$ = lower$(s1$)
t$ = lower$(s2$)
else
s$ = s1$
t$ = s2$
end if
if s$ < t$ return " comes before "
if s$ = t$ return " is equal to "
return " comes after "
end sub
s1$ = "Dog" : s2$ = "Dog"
print s1$, StringCompare$(s1$, s2$, False), s2$
s2$ = "Cat"
print s1$, StringCompare$(s1$, s2$, False), s2$
s2$ = "Rat"
print s1$, StringCompare$(s1$, s2$, False), s2$
s2$ = "dog"
print s1$, StringCompare$(s1$, s2$, False), s2$
print s1$, StringCompare$(s1$, s2$, True), s2$, " if case is ignored"
s1$ = "Dog" : s2$ = "Pig"
s3$ = StringCompare$(s1$, s2$, False)
if s3$ <> " is equal to " print s1$, " is not equal to ", s2$
end
- Output:
Igual que la entrada de FreeBASIC.
uBasic/4tH
uBasic/4tH provides a builtin, case insensitive function to compare two strings, called COMP()
which returns either a negative, zero or positive value, just like strcmp()
. In order to compare two strings case sensitive, a user defined function is required.
Print "Case sensitive"
Print "=============="
Print Show (FUNC(_Eval(FUNC(_StrCmp ("Dog", "Dog")))))
Print Show (FUNC(_Eval(FUNC(_StrCmp ("Dog", "Cat")))))
Print Show (FUNC(_Eval(FUNC(_StrCmp ("Dog", "Rat")))))
Print Show (FUNC(_Eval(FUNC(_StrCmp ("Dog", "dog")))))
Print Show (FUNC(_Eval(FUNC(_StrCmp ("Dog", "Pig")))))
Print
Print "Case insensitive"
Print "================"
Print Show (FUNC(_Eval(Comp ("Dog", "Dog"))))
Print Show (FUNC(_Eval(Comp ("Dog", "Cat"))))
Print Show (FUNC(_Eval(Comp ("Dog", "Rat"))))
Print Show (FUNC(_Eval(Comp ("Dog", "dog"))))
Print Show (FUNC(_Eval(Comp ("Dog", "Pig"))))
End
_StrCmp ' case sensitive compare
Param (2)
Local (3)
' up to the maximum length
For c@ = 0 To Max (Len (a@), Len (b@)) - 1
d@ = Iif (c@ < Len (a@), Peek (a@, c@), 0)
e@ = Iif (c@ < Len (b@), Peek (b@, c@), 0)
While (d@ = e@) ' while retrieved characters are equal
Next
Return (d@ - e@) ' return comparison
_Eval ' evaluate result
Param (1)
If a@ = 0 Then Return ("Equal")
If a@ > 0 Then Return ("Second before First")
Return ("First before Second")
Output:
Case sensitive ============== Equal Second before First First before Second First before Second First before Second Case insensitive ================ Equal Second before First First before Second Equal First before Second 0 OK, 0:673
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 %
.
( {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
);
Burlesque
blsq ) "abc""abc"==
1
blsq ) "abc""abc"!=
0
blsq ) "abc""Abc"cm
1
blsq ) "ABC""Abc"cm
-1
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
/* WRONG! */
if (strcmp(a,b)) action_on_equality();
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.
/*
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;
}
C++
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
void demo_compare(const T &a, const T &b, const std::string &semantically) {
std::cout << a << " and " << b << " are " << ((a == b) ? "" : "not ")
<< "exactly " << semantically << " equal." << std::endl;
std::cout << a << " and " << b << " are " << ((a != b) ? "" : "not ")
<< semantically << "inequal." << std::endl;
std::cout << a << " is " << ((a < b) ? "" : "not ") << semantically
<< " ordered before " << b << '.' << std::endl;
std::cout << a << " is " << ((a > b) ? "" : "not ") << semantically
<< " ordered after " << b << '.' << std::endl;
}
int main(int argc, char *argv[]) {
// Case-sensitive comparisons.
std::string a((argc > 1) ? argv[1] : "1.2.Foo");
std::string b((argc > 2) ? argv[2] : "1.3.Bar");
demo_compare<std::string>(a, b, "lexically");
// Case-insensitive comparisons by folding both strings to a common case.
std::transform(a.begin(), a.end(), a.begin(), ::tolower);
std::transform(b.begin(), b.end(), b.begin(), ::tolower);
demo_compare<std::string>(a, b, "lexically");
// Numeric comparisons; here 'double' could be any type for which the
// relevant >> operator is defined, eg int, long, etc.
double numA, numB;
std::istringstream(a) >> numA;
std::istringstream(b) >> numB;
demo_compare<double>(numA, numB, "numerically");
return (a == b);
}
- Output:
1.2.Foo and 1.3.Bar are not exactly lexically equal. 1.2.Foo and 1.3.Bar are lexicallyinequal. 1.2.Foo is lexically ordered before 1.3.Bar. 1.2.Foo is not lexically ordered after 1.3.Bar. 1.2.foo and 1.3.bar are not exactly lexically equal. 1.2.foo and 1.3.bar are lexicallyinequal. 1.2.foo is lexically ordered before 1.3.bar. 1.2.foo is not lexically ordered after 1.3.bar. 1.2 and 1.3 are not exactly numerically equal. 1.2 and 1.3 are numericallyinequal. 1.2 is numerically ordered before 1.3. 1.2 is not numerically ordered after 1.3.
Clipper
We will compare two strings, s1 and s2. The following comparisons are case sensitive.
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
To achieve case insensitive comparisons, we should use Upper() or Lower() functions:
IF Upper(s1) == Upper(s2)
? "The strings are equal"
ENDIF
Clojure
To do basic equality checks, the standard '=' operator works fine. It will do case-sensitive comparisons. To test for inequality, if simply changing the logic of your conditional isn't desirable, there is the 'not=' operator.
(= "abc" "def") ; false
(= "abc" "abc") ; true
(not= "abc" "def") ; true
(not= "abc" "abc") ; false
One of the benefits of the core '=' operator is that it is "variadic", so you can use it to test for equality of an arbitrary number of strings.
(= "abc" "abc" "abc" "abc") ; true
(= "abc" "abc" "abc" "def") ; false
If you want to test whether all the strings in a 'collection' (e.g. vector, list, sequence) are equal to one another, 'apply' is your friend.
(apply = ["abc" "abc" "abc" "abc"]) ; true
To check whether a given string is lexically before or after another, we could create functions like these, utilizing the core 'compare' function. The same compare function is used by default when one calls 'sort'.
(defn str-before [a b]
(neg? (compare a b)))
(defn str-after [a b]
(pos? (compare a b)))
(str-before "abc" "def") ; true
(str-before "def" "abc") ; false
(str-before "abc" "abc") ; false
(str-after "abc" "def") ; false
(str-after "def" "abc") ; false
(sort ["foo" "bar" "baz"]) ; ("bar" "baz" "foo")
If want a case-insensitive comparison, you need to up-case or down-case the input strings.
(defn str-caseless= [a b]
(= (clojure.string/lower-case a)
(clojure.string/lower-case b)))
(str-caseless= "foo" "fOO") ; true
This next example is contrived, but shows a bit of how you could create a "fuzzy compare" that might apply in some real case you have. For this example, we have some data which you might imagine being related to a report containing numeric values, some are actual numbers, some string representations, strings in some cases have leading or trailing whitespace. We want to get rid of whitespace, convert any number-types to string form, and then compare for equality. Note that some of the values we want to compare are integers, some are floating point values, and some aren't numeric at all.
(defn str-fuzzy= [a b]
(let [cook (fn [v] (clojure.string/trim (str v)))]
(= (cook a) (cook b))))
(str-fuzzy= "abc" " abc") ; true
(str-fuzzy= "abc" "abc ") ; true
(str-fuzzy= "abc" " abc ") ; true
(str-fuzzy= " 42 " 42) ; true
(str-fuzzy= " 42 " (* 6 7)) ; true
(str-fuzzy= " 2.5" (/ 5.0 2)) ; true
Most of the time when we compare strings, we care about whether they "look the same" and Clojure's core '=' operator uses this logic. In some cases, though, we care about whether 2 strings actually reside in the same memory location. We can check this with the 'identical?' function.
(def s1 (str "abc" "def"))
(def s2 (str "ab" "cdef"))
(= s1 "abcdef") ; true
(= s1 s2) ; true
(identical? s1 "abcdef") ; false
(identical? s1 s2) ; false
Clojure (as Java) will generally share a single copy of strings that are in the source code and known at compile time. However, strings constructed at run-time may result in many copies of the "same char sequence". When processing large data files, this can create undesirable waste. We can use Java's 'intern' method on the String class to ensure we get only one copy of each runtime-allocated string.
(defn istr [s]
(.intern s))
(def s3 (istr s1))
(def s4 (istr s2))
(= s3 s4) ; true
(identical? s3 s4) ; true
COBOL
Strings can be compared using the normal conditional syntax, like so:
"hello" = "hello" *> equality
"helloo" <> "hello" *> inequality
"aello" < "hello" *> lexical ordering
COBOL 2002 introduced the intrinsic functions LOCALE-COMPARE
and STANDARD-COMPARE
, which return one of the strings "="
, ">"
or "<"
depending on their parameters.
FUNCTION STANDARD-COMPARE("hello", "hello") *> "="
FUNCTION STANDARD-COMPARE("aello", "hello") *> "<"
FUNCTION STANDARD-COMPARE("hello", "aello") *> ">"
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.
"hello " = "hello" *> True
X"00" > X"0000" *> True
ColdFusion
- Less than: LT
- Less than or equal to: LTE
- Greater than: GT
- Greater than or equal to: GTE
- Equal to: EQ
- Not equal to: NEQ
In CFML
<cffunction name="CompareString">
<cfargument name="String1" type="string">
<cfargument name="String2" type="string">
<cfset VARIABLES.Result = "" >
<cfif ARGUMENTS.String1 LT ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is less than '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfif ARGUMENTS.String1 LTE ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is less than or equal to '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfif ARGUMENTS.String1 GT ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is greater than '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfif ARGUMENTS.String1 GTE ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is greater than or equal to '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfif ARGUMENTS.String1 EQ ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is equal to '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfif ARGUMENTS.String1 NEQ ARGUMENTS.String2 >
<cfset VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is not equal to '" & ARGUMENTS.String2 & "')" >
</cfif>
<cfreturn VARIABLES.Result >
</cffunction>
In CFScript
<cfscript>
function CompareString( String1, String2 ) {
VARIABLES.Result = "";
if ( ARGUMENTS.String1 LT ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is less than '" & ARGUMENTS.String2 & "')";
}
if ( ARGUMENTS.String1 LTE ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is less than or equal to '" & ARGUMENTS.String2 & "')";
}
if ( ARGUMENTS.String1 GT ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is greater than '" & ARGUMENTS.String2 & "')";
}
if ( ARGUMENTS.String1 GTE ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is greater than or equal to '" & ARGUMENTS.String2 & "')";
}
if ( ARGUMENTS.String1 EQ ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is equal to '" & ARGUMENTS.String2 & "')";
}
if ( ARGUMENTS.String1 NEQ ARGUMENTS.String2 ) {
VARIABLES.Result = VARIABLES.Result & "('" & ARGUMENTS.String1 & "' is not equal to '" & ARGUMENTS.String2 & "')";
}
return VARIABLES.Result;
}
</cfscript>
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:
>(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
Case-insensitive comparison functions:
> (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
Numeric strings are always compared lexically:
> (string> "45" "12345")
0
> (string> "45" "9")
NIL
Component Pascal
BlackBox Component Builder
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.
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
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
}
Delphi
procedure ShowCompares(Memo: TMemo; S1,S2: string);
begin
if S1=S2 then Memo.Lines.Add(Format('"%s" is exactly equal to "%s"',[S1,S2]));
if S1<>S2 then Memo.Lines.Add(Format('"%s" is not equal to "%s"',[S1,S2]));
if S1<S2 then Memo.Lines.Add(Format('"%s" is less than "%s"',[S1,S2]));
if S1<=S2 then Memo.Lines.Add(Format('"%s" is less than or equal to "%s"',[S1,S2]));
if S1>S2 then Memo.Lines.Add(Format('"%s" is greater than "%s"',[S1,S2]));
if S1>=S2 then Memo.Lines.Add(Format('"%s" is greater than or equal to "%s"',[S1,S2]));
if AnsiSameText(S1, S2) then Memo.Lines.Add(Format('"%s" is case insensitive equal to "%s"',[S1,S2]));
Memo.Lines.Add(Format('"%s" "%s" case sensitive different = %d',[S1,S2,AnsiCompareStr(S1,S2)]));
Memo.Lines.Add(Format('"%s" "%s" case insensitive different = %d',[S1,S2,AnsiCompareText(S1,S2)]));
Memo.Lines.Add(Format('"%s" is found at Index %d in "%s"',[S1,Pos(S1,S2),S2]));
end;
procedure ShowStringCompares(Memo: TMemo);
begin
ShowCompares(Memo,'Equal', 'Equal');
ShowCompares(Memo,'Case', 'CASE');
ShowCompares(Memo,'91', '1234');
ShowCompares(Memo,'boy', 'cowboy');
end;
- Output:
"Equal" is exactly equal to "Equal" "Equal" is less than or equal to "Equal" "Equal" is greater than or equal to "Equal" "Equal" is case insensitive equal to "Equal" "Equal" "Equal" case sensitive different = 0 "Equal" "Equal" case insensitive different = 0 "Equal" is found at Index 1 in "Equal" "Case" is not equal to "CASE" "Case" is greater than "CASE" "Case" is greater than or equal to "CASE" "Case" is case insensitive equal to "CASE" "Case" "CASE" case sensitive different = -1 "Case" "CASE" case insensitive different = 0 "Case" is found at Index 0 in "CASE" "91" is not equal to "1234" "91" is greater than "1234" "91" is greater than or equal to "1234" "91" "1234" case sensitive different = 1 "91" "1234" case insensitive different = 1 "91" is found at Index 0 in "1234" "boy" is not equal to "cowboy" "boy" is less than "cowboy" "boy" is less than or equal to "cowboy" "boy" "cowboy" case sensitive different = -1 "boy" "cowboy" case insensitive different = -1 "boy" is found at Index 4 in "cowboy" Elapsed Time: 41.211 ms.
DuckDB
The following query illustrates the various comparisons mentioned in the task description. Note in particular the use of `ILIKE` to check whether one string is "LIKE" another, ignoring case, where LIKE is the well-known SQL-style matching operation.
select s,
t,
s == t,
s != t,
s < t,
s > t,
upper(s) = upper(uppers) as "case insenstive",
'2' < '1e10',
s ilike uppers
from (select 'abc' as s, 'def' as t, 'ABC' as uppers );
- Output:
┌─────────┬─────────┬─────────┬──────────┬─────────┬─────────┬─────────────────┬────────────────┬────────────────┐ │ s │ t │ (s = t) │ (s != t) │ (s < t) │ (s > t) │ case insenstive │ ('2' < '1e10') │ (s ~~* uppers) │ │ varchar │ varchar │ boolean │ boolean │ boolean │ boolean │ boolean │ boolean │ boolean │ ├─────────┼─────────┼─────────┼──────────┼─────────┼─────────┼─────────────────┼────────────────┼────────────────┤ │ abc │ def │ false │ true │ true │ false │ true │ false │ true │ └─────────┴─────────┴─────────┴──────────┴─────────┴─────────┴─────────────────┴────────────────┴────────────────┘
DuckDB supports various collations, the standard ones being: NOCASE, NOACCENT and NFC. (The NFC collation performs NFC-normalized comparisons.)
These collations can be combined for equality checks, e.g.
D SELECT 'née' COLLATE NOCASE.NOACCENT = 'NEE'; ┌───────────────────────────────────────────┐ │ ('née' COLLATE "NOCASE.NOACCENT" = 'NEE') │ │ boolean │ ├───────────────────────────────────────────┤ │ true │ └───────────────────────────────────────────┘
Binary strings (BLOBs) can be compared for equality and inequality in the same way as VARHAR strings, but there is only one collation for BLOBs.
The ICU ("International Components for Unicode") extension provides locale-specific collations.
Dyalect
func compare(a, b) {
if a == b {
print("'\(a)' and '\(b)' are lexically equal.")
}
if a != b {
print("'\(a)' and '\(b)' are not lexically equal.")
}
if a < b {
print("'\(a)' is lexically before '\(b)'.")
}
if a > b {
print("'\(a)' is lexically after '\(b)'.")
}
if a >= b {
print("'\(a)' is not lexically before '\(b)'.")
}
if a <= b {
print("'\(a)' is not lexically after '\(b)'.")
}
}
compare("cat", "dog")
- Output:
'cat' and 'dog' are not lexically equal. 'cat' is lexically before 'dog'. 'cat' is not lexically after 'dog'.
EasyLang
a$ = "hello"
if a$ = "hello"
print "equal"
.
if a$ <> "hello2"
print "not equal"
.
if strcmp a$ "hello" = 0
print "equal"
.
if strcmp a$ "world" < 0
print "lexically before"
.
if number "10" > number "2"
print "numerically after"
.
Ecstasy
In Ecstasy, strings are objects, like all values. Any class, including classes like Int
and String
, can provide operator support by annotating the methods that represent those operators. The result is simple uniformity of how types are defined, including their operators. String comparisons rely on these operators:
module StringComparisons {
void run() {
@Inject Console console;
import ecstasy.collections.CaseInsensitive;
String[] tests = ["dog", "cat", "Dog"];
String s1 = tests[0];
for (String s2 : tests) {
// Comparing two strings for exact equality
if (s1 == s2) {
console.print($"{s1} == {s2}");
}
// Comparing two strings for inequality
if (s1 != s2) {
console.print($"{s1} != {s2}");
}
// Comparing two strings to see if one is lexically ordered
// before the other
if (s1 < s2) {
console.print($"{s1} < {s2}");
}
// Comparing two strings to see if one is lexically ordered
// after the other
if (s1 > s2) {
console.print($"{s1} > {s2}");
}
// How to achieve both case sensitive comparisons and case
// insensitive comparisons within the language
if (CaseInsensitive.areEqual(s1, s2)) {
console.print($"{s1} == {s2} (case-insensitive)");
} else {
console.print($"{s1} != {s2} (case-insensitive)");
}
switch (CaseInsensitive.compare(s1, s2)) {
case Lesser:
console.print($"{s1} < {s2} (case-insensitive)");
break;
case Equal:
// already covered this one above
assert CaseInsensitive.areEqual(s1, s2);
break;
case Greater:
console.print($"{s1} > {s2} (case-insensitive)");
break;
}
}
}
}
- Output:
dog == dog dog == dog (case-insensitive) dog != cat dog > cat dog != cat (case-insensitive) dog > cat (case-insensitive) dog != Dog dog > Dog dog == Dog (case-insensitive)
ed
No sorting/comparison, only equality. A half-baked comparison might work with character sets and alphabet splitting, but that would either be too approximate or too long to list.
Uses non-portable GNU ed case-insensitive matching suffix.
# by Artyom Bologov
H
1s/$/|/
,j
t0
1s/^\(.*\)|\1$/Strings are equal case-sensitively/
1v/Strings are equal case-sensitively/s/.*/Strings are not equal case-sensitively/
2s/^\(.*\)|\1$/Strings are equal case-insensitively/i
2v/Strings are equal case-insensitively/s/.*/Strings are not equal case-insensitively/
,p
Q
- Output:
$ ed -s equal.input < equal.ed Newline appended Strings are equal case-sensitively Strings are equal case-insensitively
Elena
ELENA 4.x:
import extensions;
compareStrings = (val1,val2)
{
if (val1 == val2) { console.printLine("The strings ",val1," and ",val2," are equal") };
if (val1 != val2) { console.printLine("The strings ",val1," and ",val2," are not equal") };
if (val1 > val2) { console.printLine("The string ",val1," is lexically after than ",val2) };
if (val1 < val2) { console.printLine("The string ",val1," is lexically before than ",val2) };
if (val1 >= val2) { console.printLine("The string ",val1," is not lexically before than ",val2) };
if (val1 <= val2) { console.printLine("The string ",val1," is not lexically after than ",val2) }
};
public program()
{
var s1 := "this";
var s2 := "that";
compareStrings(s1,s2);
console.readChar()
}
Elixir
s = "abcd"
s == "abcd" #=> true
s == "abce" #=> false
s != "abcd" #=> false
s != "abce" #=> true
s > "abcd" #=> false
s < "abce" #=> true
s >= "abce" #=> false
s <= "abce" #=> true
EMal
fun compare ← void by text a, text b
writeLine("Comparing `", a, "` and `", b, "`:")
text la ← a.lower()
text lb ← b.lower()
writeLine(" `", a, "` æ `", b, "` case sensitively: ", a æ b, ", case insensitively: ", la æ lb)
writeLine(" `", a, "` ≠ `", b, "` case sensitively: ", a ≠ b, ", case insensitively: ", la ≠ lb)
writeLine(" `", a, "` ◇ `", b, "` case sensitively: ", a ◇ b, ", case insensitively: ", la ◇ lb)
writeLine(" `", a, "` < `", b, "` case sensitively: ", a < b, ", case insensitively: ", la < lb)
writeLine(" `", a, "` > `", b, "` case sensitively: ", a > b, ", case insensitively: ", la > lb)
writeLine(" `", a, "` ≤ `", b, "` case sensitively: ", a ≤ b, ", case insensitively: ", la ≤ lb)
writeLine(" `", a, "` ≥ `", b, "` case sensitively: ", a ≥ b, ", case insensitively: ", la ≥ lb)
end
List samples ← Pair[text%text("Hello" ⇒ "Hello"), text%text("5" ⇒ "5.0"),
text%text("java" ⇒ "Java"), text%text("ĴÃVÁ" ⇒ "ĴÃVÁ"), text%text("ĴÃVÁ" ⇒ "ĵãvá")]
samples.list(<Pair pair|compare(pair.key, pair.value))
- Output:
Comparing `Hello` and `Hello`: `Hello` æ `Hello` case sensitively: ⊤, case insensitively: ⊤ `Hello` ≠ `Hello` case sensitively: ⊥, case insensitively: ⊥ `Hello` ◇ `Hello` case sensitively: 0, case insensitively: 0 `Hello` < `Hello` case sensitively: ⊥, case insensitively: ⊥ `Hello` > `Hello` case sensitively: ⊥, case insensitively: ⊥ `Hello` ≤ `Hello` case sensitively: ⊤, case insensitively: ⊤ `Hello` ≥ `Hello` case sensitively: ⊤, case insensitively: ⊤ Comparing `5` and `5.0`: `5` æ `5.0` case sensitively: ⊥, case insensitively: ⊥ `5` ≠ `5.0` case sensitively: ⊤, case insensitively: ⊤ `5` ◇ `5.0` case sensitively: -1, case insensitively: -1 `5` < `5.0` case sensitively: ⊤, case insensitively: ⊤ `5` > `5.0` case sensitively: ⊥, case insensitively: ⊥ `5` ≤ `5.0` case sensitively: ⊤, case insensitively: ⊤ `5` ≥ `5.0` case sensitively: ⊥, case insensitively: ⊥ Comparing `java` and `Java`: `java` æ `Java` case sensitively: ⊥, case insensitively: ⊤ `java` ≠ `Java` case sensitively: ⊤, case insensitively: ⊥ `java` ◇ `Java` case sensitively: -1, case insensitively: 0 `java` < `Java` case sensitively: ⊤, case insensitively: ⊥ `java` > `Java` case sensitively: ⊥, case insensitively: ⊥ `java` ≤ `Java` case sensitively: ⊤, case insensitively: ⊤ `java` ≥ `Java` case sensitively: ⊥, case insensitively: ⊤ Comparing `ĴÃVÁ` and `ĴÃVÁ`: `ĴÃVÁ` æ `ĴÃVÁ` case sensitively: ⊤, case insensitively: ⊤ `ĴÃVÁ` ≠ `ĴÃVÁ` case sensitively: ⊥, case insensitively: ⊥ `ĴÃVÁ` ◇ `ĴÃVÁ` case sensitively: 0, case insensitively: 0 `ĴÃVÁ` < `ĴÃVÁ` case sensitively: ⊥, case insensitively: ⊥ `ĴÃVÁ` > `ĴÃVÁ` case sensitively: ⊥, case insensitively: ⊥ `ĴÃVÁ` ≤ `ĴÃVÁ` case sensitively: ⊤, case insensitively: ⊤ `ĴÃVÁ` ≥ `ĴÃVÁ` case sensitively: ⊤, case insensitively: ⊤ Comparing `ĴÃVÁ` and `ĵãvá`: `ĴÃVÁ` æ `ĵãvá` case sensitively: ⊥, case insensitively: ⊤ `ĴÃVÁ` ≠ `ĵãvá` case sensitively: ⊤, case insensitively: ⊥ `ĴÃVÁ` ◇ `ĵãvá` case sensitively: 1, case insensitively: 0 `ĴÃVÁ` < `ĵãvá` case sensitively: ⊥, case insensitively: ⊥ `ĴÃVÁ` > `ĵãvá` case sensitively: ⊤, case insensitively: ⊥ `ĴÃVÁ` ≤ `ĵãvá` case sensitively: ⊥, case insensitively: ⊤ `ĴÃVÁ` ≥ `ĵãvá` case sensitively: ⊤, case insensitively: ⊤
Erlang
Examples from Erlang shell:
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
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.
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
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)
Factor
Strings in Factor are just sequences of unicode code points, so the usual sequence operations apply to strings. The <=> word from the math.order vocabulary can be used to lexically compare strings, and Factor includes the human<=> word in the sorting.human vocabulary for comparing numeric strings like a human would.
USING: ascii math.order sorting.human ;
IN: scratchpad "foo" "bar" = . ! compare for equality
f
IN: scratchpad "foo" "bar" = not . ! compare for inequality
t
IN: scratchpad "foo" "bar" before? . ! lexically ordered before?
f
IN: scratchpad "foo" "bar" after? . ! lexically ordered after?
t
IN: scratchpad "Foo" "foo" <=> . ! case-sensitive comparison
+lt+
IN: scratchpad "Foo" "foo" [ >lower ] bi@ <=> . ! case-insensitive comparison
+eq+
IN: scratchpad "a1" "a03" <=> . ! comparing numeric strings
+gt+
IN: scratchpad "a1" "a03" human<=> . ! comparing numeric strings like a human
+lt+
Falcon
'VBA/Python programmer's approach. I'm just a junior Falconeer but this code seems to go the falcon way
/* created by Aykayayciti Earl Lamont Montgomery
April 9th, 2018 */
e = "early"
l = "toast"
g = "cheese"
b = "cheese"
e2 = "early"
num1 = 123
num2 = 456
> e == e2 ? @ "$e equals $e2" : @ "$e does not equal $e2"
> e != e2 ? @ "$e does not equal $e2": @ "$e equals $e2"
// produces -1 for less than
> b.cmpi(l) == 1 ? @ "$b is grater than $l" : @ "$l is grater than $b"
// produces 1 for greater than
> l.cmpi(b) == 1 ? @ "$l is grater than $b" : @ "$b is grater than $l"
// produces 0 for equal (but could be greater than or equal)
> b.cmpi(g) == 1 or b.cmpi(g) == 0 ? @ "$b is grater than or equal to $g" : @ "$b is not >= $g"
// produces 0 for equal (but could be less than or equal)
>b.cmpi(g) == -1 or b.cmpi(g) == 0 ? @ "$b is less than or equal to $g" : @ "$b is not <= $g"
function NumCompare(num1, num2)
if num1 < num2
ans = " < "
elif num1 > num2
ans = " > "
else
ans = " = "
end
return ans
end
result = NumCompare(num1, num2)
> @ "$num1 $result $num2"
- Output:
early equals early early equals early toast is grater than cheese toast is grater than cheese cheese is grater than or equal to cheese cheese is less than or equal to cheese 123 < 456 [Finished in 0.2s]
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.
: 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>= ;
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.
Fortran
Early Fortran offered no facilities for manipulating text, only numbers, though the FORMAT statement could present text via the "Hollerith" format code of nH, where n characters follow the H, as in
PRINT 42,N
42 FORMAT (14HThe answer is ,I9)
- though the use of lower-case here is anachronistic. There was an odd facility whereby using such a FORMAT statement in a READ statement would cause the Hollerith text to be replaced by what was read in, and this new text could be written out by a later PRINT statement - but the program could not inspect the text at all. So no string comparison.
Fortran IV introduced the Aw format code, where w was an integer such as one or two, and this transferred the bit pattern "as is" to or from a variable in a READ or WRITE statement. A sixteen-bit integer would suit either A1 or A2, a thirty-two bit floating-point variable could hold up to four eight-bit character codes, and so on, though with caution because some computers had eighteen-bit words and others forty-eight bit words, not just powers of two. An array of integers might be used to hold a line of text, and A1 format (one character per integer) would be easier for manipulation, while A2 would use less storage. The variables could be compared as numerical values and so string comparison was possible. However, the numerical values would be quite strange, because A1 format would place the bit pattern at the high-order end of the word (where the sign bit would be found in integers), and with floating-point variables the resulting values would be even more surprising. On the B6700, the high-order bit of a 48-bit word was not employed in arithmetic at all. Even so, in this period, interpreters for SNOBOL (surely the epitome of string-manipulation languages) were often written in Fortran, because of its portability. So, string comparison in the same way as number comparison.
Fortran 66 introduced the LOGICAL type and the logical-IF statement, that used comparison operations: mnemonics "stropped" by periods: .LT.
.LE.
.EQ.
.NE.
.GE.
.GT.
and more flexible compilers (F90 and later) also recognise respectively <
<=
==
(a single = being committed to representing assignment) /=
(most ASCII keyboards lacking a ¬ character, present on IBM keyboards for EBCDIC) >=
>
. The scope of these operations was extended when Fortran 77 introduced the CHARACTER*n TEXT type, whereby a variable was declared to have a fixed amount of space, of n characters, and trailing spaces were usual. There is no string "length" attribute and LEN(TEXT) does not report the current length of the string but its size, which remains n. F90 however introduced facilities whereby a character variable could be redefined to have the required size each time it has a value assigned to it, and this scheme became part of the language with F2003.
Character string comparison is straightforward when both entities are character, and the usage has the same form as when both are numeric. There is no facility for comparing a numeric value such as 12345 to a character sequence "12345" because these are of incompatible types with very different bit patterns. You would have to convert the number to a character sequence, or the character sequence to a number - which last is complicated by the possibility of character sequences not presenting a valid number, as in "12three45". Thus, the comparison operators are polymorphic in application (to characters or to numbers) but unbending in use as a comparison can only be made of the same type entities. Similarly, although the existence of > etc. implies the operation of subtraction, this is not allowed for character variables and so the three-way choice of result via the arithmetic-IF is unavailable.
Exact matching is problematic, because trailing spaces are disregarded so that "blah" .EQ. "blah "
yields true. Thus, the quality of equality is strained. To test for "exact" equality the lengths would have to be compared also, somewhat as in TEXT1.EQ.TEXT2 .AND. LEN(TEXT1).EQ.LEN(TEXT2)
All character comparisons are literal: case counts. There is no facility for case insensitive comparison (though in principle a compiler could offer to do so via non-standard mnemonics) and there often are no library routines for case conversion. The usual procedure is to copy both items to scratch variables (with all the annoyance of "how big?"), convert both to upper case (or both to lower case) and then compare. Or, rather than copying the strings, one might code for a character-by-character comparison and handling case differences one character at a time. With single-character comparison one can use ICHAR(c) to obtain the numerical value of the character code, and this enables the use of the three-way test of the arithmetical-IF as in IF (ICHAR(TEXT1(L:L)) - ICHAR(TEXT2(L:L))) negative,equal,positive
, where negative would be the statement label jumped to should character L of TEXT2 be greater than character L of TEXT1. With equality, one would increment L and after checking that TEXT1 and TEXT2 had another character L available, test afresh.
To accommodate case insensitivity, one could use an AND operation to mask off the bits distinguishing a lower case letter from an upper case letter, but should non-letter characters be involved, this may mask other differences as well. Instead, prepare an array of 256 integers, say UC, where UC(i) = i except for those indices corresponding to the character code values of the lower case letters, for which the array has instead the value of the corresponding upper case letter. Then the comparison might be IF (UC(ICHAR(TEXT1(L:L))) - UC(ICHAR(TEXT2(L:L)))) negative,equal,positive
so that case insensitivity is achieved without the annoyance of multiple testing or case conversion but at the cost of array access. And by re-arranging values in array UC, a custom ordering of the character codes could be achieved at no extra cost.
FreeBASIC
' FB 1.05.0
' Strings in FB natively support the relational operators which compare lexically on a case-sensitive basis.
' There are no special provisions for numerical strings.
' There are no other types of string comparison for the built-in types though 'user defined types'
' can specify their own comparisons by over-loading the relational operators.
Function StringCompare(s1 As Const String, s2 As Const String, ignoreCase As Boolean = false) As String
Dim As String s, t ' need new string variables as the strings passed in can't be changed
If ignoreCase Then
s = LCase(s1)
t = LCase(s2)
Else
s = s1
t = s2
End If
If s < t Then Return " comes before "
If s = t Then Return " is equal to "
Return " comes after "
End Function
Dim As Integer result
Dim As String s1, s2, s3
s1 = "Dog" : s2 = "Dog"
Print s1; StringCompare(s1, s2); s2
s2 = "Cat"
Print s1; StringCompare(s1, s2); s2
s2 = "Rat"
Print s1; StringCompare(s1, s2); s2
s2 = "dog"
Print s1; StringCompare(s1, s2); s2
Print s1; StringCompare(s1, s2, True); s2; " if case is ignored"
s1 = "Dog" : s2 = "Pig"
s3 = StringCompare(s1, s2)
If s3 <> " is equal to " Then
Print s1; " is not equal to "; s2
End If
Print
Print "Press any key to quit"
Sleep
- Output:
c:\FreeBasic>stringcompare Dog is equal to Dog Dog comes after Cat Dog comes before Rat Dog comes before dog Dog is equal to dog if case is ignored Dog is not equal to Pig
FutureBasic
void local fn StringComparison
CFStringRef s1, s2
NSComparisonResult result
window 1, @"String Comparison"
print @"• equal - case sensitive •"
s1 = @"alpha" : s2 = @"alpha"
if ( fn StringIsEqual( s1, s2 ) )
printf @"\"%@\" is equal to \"%@\"",s1,s2
end if
result = fn StringCompare( s1, s2 )
if ( result == NSOrderedSame )
printf @"\"%@\" is equal to \"%@\"",s1,s2
end if
select ( s1 )
case s2
printf @"\"%@\" is equal to \"%@\"",s1,s2
case else
printf @"\"%@\" is not equal to \"%@\"",s1,s2
end select
print @"\n• not equal - case sensitive •"
s2 = @"bravo"
if ( fn StringIsEqual( s1, s2 ) == NO )
printf @"\"%@\" is not equal to \"%@\"",s1,s2
end if
result = fn StringCompare( s1, s2 )
if ( result != NSOrderedSame )
printf @"\"%@\" is not equal to \"%@\"",s1,s2
end if
select ( s1 )
case s2
printf @"\"%@\" is equal to \"%@\"",s1,s2
case else
printf @"\"%@\" is not equal to \"%@\"",s1,s2
end select
print @"\n• ordered before - case sensitive •"
result = fn StringCompare( s1, s2 )
if ( result == NSOrderedAscending )
printf @"\"%@\" is ordered before \"%@\"",s1,s2
end if
print @"\n• ordered after - case sensitive •"
result = fn StringCompare( s2, s1 )
if ( result == NSOrderedDescending )
printf @"\"%@\" is ordered after \"%@\"",s2,s1
end if
print @"\n• equal - case insensitive •"
s2 = @"AlPhA"
result = fn StringCaseInsensitiveCompare( s1, s2 )
if ( result == NSOrderedSame )
printf @"\"%@\" is equal to \"%@\"",s1,s2
end if
result = fn StringCompareWithOptions( s1, s2, NSCaseInsensitiveSearch )
if ( result == NSOrderedSame )
printf @"\"%@\" is equal to \"%@\"",s1,s2
end if
if ( fn StringIsEqual( lcase(s1), lcase(s2) ) )
printf @"\"%@\" is equal to \"%@\"",s1,s2
end if
end fn
fn StringComparison
HandleEvents
- Output:
• equal - case sensitive • "alpha" is equal to "alpha" "alpha" is equal to "alpha" "alpha" is equal to "alpha" • not equal - case sensitive • "alpha" is not equal to "bravo" "alpha" is not equal to "bravo" "alpha" is not equal to "bravo" • ordered before - case sensitive • "alpha" is ordered before "bravo" • ordered after - case sensitive • "bravo" is ordered after "alpha" • equal - case insensitive • "alpha" is equal to "AlPhA" "alpha" is equal to "AlPhA" "alpha" is equal to "AlPhA"
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.
}
- 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.
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
To achieve case insensitive comparisons, we should use Upper() or Lower() functions:
IF Upper( s1 ) == Upper( s2 )
? "The strings are equal"
ENDIF
Haskell
Examples from the Haskell shell:
> "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
Icon and Unicon
Same in both languages.
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
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:
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
Note that boxopen
is used here so that these operations do not distinguish between the types sequence of characters and boxed sequence of characters. If distinguishing between these types would be desirable, boxopen
should be replaced with >
or a separate test should also be used, such as -:&datatype
.
Usage:
'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
Java
A String object in Java represents a UTF-16 string. Comparisons are done using the equals(), equalsIgnoreCase(), compareTo(), and compareToIgnoreCase() methods.
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));
}
}
- 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
JavaScript
/*
== equal value
=== equal value and equal type
!= not equal value
!== not equal value or not equal type
< lexically ordered before
> lexically ordered after
*/
console.log(
"abcd" == "abcd", // true
"abcd" === "abcd", // true
123 == "123", // true
123 === "123", // false
"ABCD" == "abcd", // false
"ABCD" != "abcd", // true
123 != "123", // false
123 !== "123", // true
"abcd" < "dcba", // true
"abcd" > "dcba", // false
"ABCD".toLowerCase() == "abcd".toLowerCase(), // true (case insensitive)
)
jq
jq strings are JSON strings. The jq comparison operators (==, !=, <, <=, >=, >) can be used to compare strings or indeed 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.
# 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 <
jq provides `ascii_downcase` and `ascii_upcase` for ASCII case conversion. With the caveat that these are what they are, case-insensitive comparisons can be achieved as illustrated by this example:
("AtoZ" | ascii_upcase) == ("atoz" | ascii_upcase) # true
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 and an option to turn case-sensitivity off. Please see Builtin Operators and Functions for details.
Julia
Notes:
- Julia is strongly typed and not coherce Numbers to/from Chars neither Chars to/from Strings;
- In Julia /constant/ chars and strings are differently enclosed in ' for chars and " for strings;
- Julia can handle both ASCII and non-ASCII chars;
function compare(a, b)
println("\n$a is of type $(typeof(a)) and $b is of type $(typeof(b))")
if a < b println("$a is strictly less than $b") end
if a <= b println("$a is less than or equal to $b") end
if a > b println("$a is strictly greater than $b") end
if a >= b println("$a is greater than or equal to $b") end
if a == b println("$a is equal to $b") end
if a != b println("$a is not equal to $b") end
if a === b println("$a has object identity with $b") end
if a !== b println("$a has negated object identity with $b") end
end
compare("YUP", "YUP")
compare('a', 'z')
compare("24", "123")
compare(24, 123)
compare(5.0, 5)
- 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 YUP has negated object identity with YUP a is of type Char and z is of type Char a is strictly less than z a is less than or equal to z a is not equal to z a has negated object identity with z 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 has negated object identity with 123 24 is of type Int64 and 123 is of type Int64 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 Float64 and 5 is of type Int64 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
Kotlin
// version 1.0.6
fun main(args: Array<String>) {
val k1 = "kotlin"
val k2 = "Kotlin"
println("Case sensitive comparisons:\n")
println("kotlin and Kotlin are equal = ${k1 == k2}")
println("kotlin and Kotlin are not equal = ${k1 != k2}")
println("kotlin comes before Kotlin = ${k1 < k2}")
println("kotlin comes after Kotlin = ${k1 > k2}")
println("\nCase insensitive comparisons:\n")
println("kotlin and Kotlin are equal = ${k1 == k2.toLowerCase()}")
println("kotlin and Kotlin are not equal = ${k1 != k2.toLowerCase()}")
println("kotlin comes before Kotlin = ${k1 < k2.toLowerCase()}")
println("kotlin comes after Kotlin = ${k1 > k2.toLowerCase()}")
}
- Output:
Case sensitive comparisons: kotlin and Kotlin are equal = false kotlin and Kotlin are not equal = true kotlin comes before Kotlin = false kotlin comes after Kotlin = true Case insensitive comparisons: kotlin and Kotlin are equal = true kotlin and Kotlin are not equal = false kotlin comes before Kotlin = false kotlin comes after Kotlin = false
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
- 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
Lingo
Lingo's built-in string comparison is case-insensitive:
put "abc"="ABC"
-- 1
put "abc"<>"def"
-- 1
put "abc"<"def"
-- 1
put "abc">"def"
-- 0
Case-sensitive string comparison could be implemented e.g. like this:
-- Returns -1 if str1 is less than str2
-- Returns 1 if str1 is greater than str2
-- Returns 0 if str1 and str2 are equal
on strcmp (str1, str2)
h1 = bytearray(str1).toHexString(1, str1.length)
h2 = bytearray(str2).toHexString(1, str2.length)
if h1<h2 then return -1
else if h1>h2 then return 1
return 0
end
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.
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)
- 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 /Wolfram Language
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"]
- 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
MATLAB / Octave
a="BALL";
b="BELL";
if a==b, disp('The strings are equal'); end;
if strcmp(a,b), disp('The strings are equal'); end;
if a~=b, disp('The strings are not equal'); end;
if ~strcmp(a,b), disp('The strings are not equal'); end;
if a > b, disp('The first string is lexically after than the second'); end;
if a < b, disp('The first string is lexically before than the second'); end;
if a >= b, disp('The first string is not lexically before than the second'); end;
if a <= b, disp('The first string is not lexically after than the second'); end;
% to make a case insensitive comparison convert both strings to the same lettercase:
a="BALL";
b="ball";
if strcmpi(a,b), disp('The first and second string are the same disregarding letter case'); end;
if lower(a)==lower(b), disp('The first and second string are the same disregarding letter case'); end;
- Output:
The strings are not equal The strings are not equal The first string is lexically before than the second The first string is not lexically after than the second The first and second string are the same disregarding letter case The first and second string are the same disregarding letter case
MiniScript
string1 = input("Please enter a string.")
string2 = input("Please enter a second string.")
//Comparing two strings for exact equality
if string1 == string2 then
print "Strings are equal."
end if
//Comparing two strings for inequality
if string1 != string2 then
print "Strings are NOT equal."
end if
//Comparing two strings to see if one is lexically ordered before than the other
if string1 > string2 then
print string1 + " is lexically ordered AFTER " + string2
//Comparing two strings to see if one is lexically ordered after than the other
else if string1 < string2 then
print string1 + " is lexically ordered BEFORE " + string2
end if
//How to achieve case sensitive comparisons
//Comparing two strings for exact equality (case sensitive)
if string1 == string2 then
print "Strings are equal. (case sensitive)"
end if
//Comparing two strings for inequality (case sensitive)
if string1 != string2 then
print "Strings are NOT equal. (case sensitive)"
end if
//How to achieve case insensitive comparisons within the language
//Comparing two strings for exact equality (case insensitive)
if string1.lower == string2.lower then
print "Strings are equal. (case insensitive)"
end if
//Comparing two strings for inequality (case insensitive)
if string1.lower != string2.lower then
print "Strings are NOT equal. (case insensitive)"
end if
Nanoquery
While many comparisons in Nanoquery yield the same results as Python, numeric strings are coerced into numeric types, so comparison between numeric strings yields the same results as the equivalent numeric types.
def compare(a, b)
println format("\n%s is of type %s and %s is of type %s", a, type(a), b, type(b))
if a < b
println format("%s is strictly less than %s", a, b)
end
if a <= b
println format("%s is less than or equal to %s", a, b)
end
if a > b
println format("%s is strictly greater than %s", a, b)
end
if a >= b
println format("%s is greater than or equal to %s", a, b)
end
if a = b
println format("%s is equal to %s", a, b)
end
if a != b
println format("%s is not equal to %s", a, b)
end
end
compare("YUP", "YUP")
compare("BALL", "BELL")
compare("24", "123")
compare(24, 123)
compare(5.0, 5)
- Output:
YUP is of type java.lang.String and YUP is of type java.lang.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 java.lang.String and BELL is of type java.lang.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 java.lang.String and 123 is of type java.lang.String 24 is strictly less than 123 24 is less than or equal to 123 24 is not equal to 123 24 is of type Nanoquery.Lang.Integer and 123 is of type Nanoquery.Lang.Integer 24 is strictly less than 123 24 is less than or equal to 123 24 is not equal to 123 5.0 is of type Nanoquery.Lang.Float and 5 is of type Nanoquery.Lang.Integer 5.0 is less than or equal to 5 5.0 is greater than or equal to 5 5.0 is not equal to 5
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.
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"
The list of strict comparison operators described in the REXX sample apply to NetRexx too.
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)
# cmpIgnoreCase(a, b) => 0 if a == b; < 0 if a < b; > 0 if a > b
echo("cmpIgnoreCase :", s1.cmpIgnoreCase s2)
- Output:
== : false != : true < : false <= : false > : true >= : true cmpIgnoreCase: 0
Oforth
"abcd" "abcd" ==
"abcd" "abce" <>
"abcd" "abceed" <=
"abce" "abcd" >
"abcEEE" toUpper "ABCeee" toUpper ==
ooRexx
See the NetRexx and/or the REXX implementation.
There is a way to "caseless" compare array elements:
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
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:
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');
- 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
Phix
with javascript_semantics string name="Pete" if name=="pete" then ?"The strings are equal" end if if name!="pete" then ?"The strings are not equal" end if if name<"pete" then ?"name is lexically first" end if if name>"pete" then ?"name is lexically last" end if if upper(name)=upper("pete") then ?"case insensitive match" end if if match("pete",lower(name)) then ?"petes in there somewhere" end if
- Output:
"The strings are not equal" "name is lexically first" "case insensitive match" "petes in there somewhere"
Phixmonti
/# Rosetta Code problem: https://rosettacode.org/wiki/String_comparison
by Galileo, 11/2022 #/
include ..\Utilitys.pmt
"Pete" >ps
"pete" tps == if "The strings are equal" ? endif
"pete" tps != if "The strings are not equal" ? endif
tps "pete" < if ( tps " is lexically first" ) lprint nl endif
tps "pete" > if ( tps " is lexically last" ) lprint nl endif
tps upper "pete" upper == if "case insensitive match" ? endif
ps> lower "pete" find if "petes in there somewhere" ? endif
- Output:
The strings are not equal Pete is lexically first case insensitive match petes in there somewhere === Press any key to exit ===
Picat
main =>
S1 = "abc",
S2 = "def",
S1 == S2, % -> false.
S1 != S2, % -> true.
S1 @< S2, % -> true. Is S1 lexicographically less than S1?
S1 @> S2, % -> false.
to_lowercase(S1) == to_lowercase(S2), % -> false.
"1234" @> "123", % -> true. lexical comparison
"1234" @< 12342222, % -> false. No coersion is done. Numbers are always ordered before strings
123 < 1234. % -> true '<' is used only for numbers
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)
PowerShell
"a" -lt "b" # lower than
"a" -eq "b" # equal
"a" -gt "b" # greater than
"a" -le "b" # lower than or equal
"a" -ne "b" # not equal
"a" -ge "b" # greater than or equal
Output:
True False False True True False
By default operators are case insensitive. Preceed them by the letter "c" to make them case sensitive like this:
"a" -eq "A"
"a" -ceq "A"
True False
PureBasic
Macro StrTest(Check,tof)
Print("Test "+Check+#TAB$)
If tof=1 : PrintN("true") : Else : PrintN("false") : EndIf
EndMacro
Procedure.b StrBool_eq(a$,b$) : ProcedureReturn Bool(a$=b$) : EndProcedure
Procedure.b StrBool_n_eq(a$,b$) : ProcedureReturn Bool(a$<>b$) : EndProcedure
Procedure.b StrBool_a(a$,b$) : ProcedureReturn Bool(a$>b$) : EndProcedure
Procedure.b StrBool_b(a$,b$) : ProcedureReturn Bool(a$<b$) : EndProcedure
Procedure.b NumBool_eq(a$,b$) : ProcedureReturn Bool(Val(a$)=Val(b$)) : EndProcedure
Procedure.b NumBool_n_eq(a$,b$) : ProcedureReturn Bool(Val(a$)<>Val(b$)) : EndProcedure
Procedure.b NumBool_a(a$,b$) : ProcedureReturn Bool(Val(a$)>Val(b$)) : EndProcedure
Procedure.b NumBool_b(a$,b$) : ProcedureReturn Bool(Val(a$)<Val(b$)) : EndProcedure
Procedure Compare(a$,b$,cs.b=1,num.b=0)
If Not cs : a$=UCase(a$) : b$=UCase(b$) : EndIf
PrintN("a = "+a$) : PrintN("b = "+b$)
If Not num : StrTest(" a=b ",StrBool_eq(a$,b$)) : Else : StrTest(" a=b ",NumBool_eq(a$,b$)) : EndIf
If Not num : StrTest(" a<>b ",StrBool_n_eq(a$,b$)) : Else : StrTest(" a<>b ",NumBool_n_eq(a$,b$)) : EndIf
If Not num : StrTest(" a>b ",StrBool_a(a$,b$)) : Else : StrTest(" a>b ",NumBool_a(a$,b$)) : EndIf
If Not num : StrTest(" a<b ",StrBool_b(a$,b$)) : Else : StrTest(" a<b ",NumBool_b(a$,b$)) : EndIf
EndProcedure
If OpenConsole()
PrintN("String comparison - ")
a$="Abcd" : b$="abcd"
PrintN(#CRLF$+"- case sensitive:")
Compare(a$,b$)
PrintN(#CRLF$+"- case insensitive:")
Compare(a$,b$,0)
a$="1241" : b$="222"
PrintN(#CRLF$+"- num-string; lexically compared:")
Compare(a$,b$)
PrintN(#CRLF$+"- num-string; numerically compared:")
Compare(a$,b$,1,1)
Input()
EndIf
- Output:
String comparison - - case sensitive: a = Abcd b = abcd Test a=b false Test a<>b true Test a>b false Test a<b true - case insensitive: a = ABCD b = ABCD Test a=b true Test a<>b false Test a>b false Test a<b false - num-string; lexically compared: a = 1241 b = 222 Test a=b false Test a<>b true Test a>b false Test a<b true - num-string; numerically compared: a = 1241 b = 222 Test a=b false Test a<>b true Test a>b true Test a<b false
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.
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)
- 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
QB64
Dim As String String1, String2
' direct string comparison using case sensitive
String1 = "GWbasic"
String2 = "QuickBasic"
If String1 = String2 Then Print String1; " is equal to "; String2 Else Print String1; " is NOT egual to "; String2
String1 = "gWbasic"
String2 = "GWBasic"
If String1 = String2 Then Print String1; " is equal to "; String2 Else Print String1; " is NOT egual to "; String2
' direct string comparison using case insensitive
If UCase$(String1) = UCase$(String2) Then Print String1; " is equal to "; String2; Else Print String1; " is NOT egual to "; String2;
Print " case insensitive"
String1 = "GwBasiC"
String2 = "GWBasic"
If LCase$(String1) = LCase$(String2) Then Print String1; " is equal to "; String2; Else Print String1; " is NOT egual to "; String2;
Print " case insensitive"
' lexical order
String1 = "AAAbbb"
String2 = "AaAbbb"
If String1 > String2 Then Print String1; " is after "; String2 Else Print String1; " is before "; String2
' number in string format comparison
String1 = "0123"
String2 = "5"
' lexical order
If String1 > String2 Then Print String1; " is after "; String2 Else Print String1; " is before "; String2
' value order
If Val(String1) > Val(String2) Then Print String1; " is bigger than "; String2 Else Print String1; " is lower "; String2
Print "QB64, like QBasic, has native coercive/allomorphic operators for string type variable"
End
Quackery
As a dialogue in the Quackery shell.
/O> ( compare two strings for equality ) ... $ "abc" $ "xyz" = ... echo ( 0 = false, 1 = true ) ... 0 Stack empty. /O> ( compare two strings for inequality ) ... $ "abc" $ "xyz" != ... echo ( 0 = false, 1 = true ) ... 1 Stack empty. //O> ( compare two strings to see if one is lexically ordered before the other ) ... $ "abc" $ "xyz" $< ... echo ( 0 = false, 1 = true ) ... 1 Stack empty. /O> ( compare two strings to see if one is lexically ordered after the other ) ... $ "abc" $ "xyz" $> ... echo ( 0 = false, 1 = true ) ... 1 Stack empty. /O> ( for case insensitive, convert both strings to the same case ) ... [ $ "" swap witheach [ upper join ] ] is upper$ ( $ --> $ ) ... $ "AbC" upper$ $ "aBc" upper$ = ... echo ( 0 = false, 1 = true ) ... 1 Stack empty. /O> ( Numeric strings are not treated differently to other strings. ) ... ( Lexical ordering uses QACSFOT rather than ASCII/Unicode ordering. ) ( ) ... ( "Quackery Arbitrary Character Sequence For Ordered Text" ) ... ( 0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrS ) ... ( sTtUuVvWwXxYyZz()[]{}<>~=+-*/^\|_.,:;?!'"`%@&#$ ) ... Stack empty.
R
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)
- 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:
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(op[[i]](a, b)) printer(a, b, msgs[i]))
invisible()
}
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")
Raku
(formerly Perl 6)
Raku 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.)
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;
- 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
Unicode normalization by default
Be aware that Raku applies normalization (Unicode NFC form (Normalization Form Canonical)) by default to all input and output except for file names See docs. Raku follows the Unicode spec. Raku follows all of the Unicode spec, including parts that some people don't like. There are some graphemes for which the Unicode consortium has specified that the NFC form is a different (though usually visually identical) grapheme. Referred to in Unicode standard annex #15 as Canonical Equivalence. Raku adheres to that spec.
One that people seem to get hung up on is the Kelvin symbol "K" getting automatically converted to ASCII uppercase "K".
say "\c[KELVIN SIGN]".uniname;
# => LATIN CAPITAL LETTER K
my $kelvin = "\c[KELVIN SIGN]";
my $k = "\c[LATIN CAPITAL LETTER K]";
say ($kelvin eq $k); # True, lexically equal
say ($kelvin eqv $k); # True, generically equal
say ($kelvin === $k); # True, identical objects
In most programming language the previous two objects wouldn't be equivalent, but since Raku follows the Unicode specification, and normalization is applied automatically, they show up as equivalent.
It's officially identified as a possible trap for string handling. See docs.
Relation
set a = "Hello"
set b = "World"
if a == b
' a is equal to b (case sensitive)
end if
if lower(a) == lower(b)
' a is equal to b (case insensitive)
end if
if a !== b
' a is not equal to b (case sensitive)
end if
if lower(a) !== lower(b)
' a is not equal to b (case insensitive)
end if
if a << b
' a is lexically first to b (case sensitive)
end if
if lower(a) << lower(b)
' a is lexically first to b (case insensitive)
end if
if a >> b
' a is lexically after b (case sensitive)
end if
if lower(a) >> Lower(b)
' a is lexically after b (case insensitive)
end if
Variables in Relation are not typed. They are treated as numbers of string depending on the operator. Numbers are always treated as strings, if you use the operators ==, !==, << and >>
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.
/*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. */
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:
/* 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)'"'
Output:
"A" < "a" -> 0 "A" = " a" -> 1 "A" == " a" -> 0 "Walter" < " Wolter" -> 1
Ring
if s1 = s2
See "The strings are equal"
ok
if not (s1 = s2)
See "The strings are not equal"
ok
if strcmp(s1,s2) > 0
see "s2 is lexically ordered before than s1"
ok
if strcmp(s1,s2) < 0
see "s2 is lexically ordered after than s1"
ok
To achieve case insensitive comparisons, we should use Upper() or Lower() functions:
if Upper(s1) = Upper(s2)
see "The strings are equal"
ok
Robotic
We can use "if" statements to compare strings, albeit in a simple way.
Things to note: Numeric strings are lexicographically compared the same way as a regular string. There is no opposite of the case-sensitive comparison.
set "$str1" to "annoy"
set "$str2" to "annoy"
: "loop"
if "$str1" === "$str2" then "case_equal"
if "$str1" = "$str2" then "equal"
if "$str1" > "$str2" then "greater_than"
if "$str1" < "$str2" then "less_than"
end
: "case_equal"
* "&$str1& is case equal to &$str2&"
set "$str2" to "ANNOY"
goto "loop"
: "equal"
* "&$str1& is equal to &$str2&"
set "$str2" to "allow"
wait for 100
goto "loop"
: "greater_than"
* "&$str1& is lexicographically greater than &$str2&"
set "$str1" to "aardvark"
wait for 100
goto "loop"
: "less_than"
* "&$str1& is lexicographically less than &$str2&"
end
RPL
Equality can be tested either with ==
or SAME
operators:
"ab" "abc" ==
returns 0 (false).
To test inequality:
"ab" "abc" ≠
returns 1 (true).
Lexical order can be checked with <
, ≤
, >
or ≥
operators.
"ab" "abc" ≤
returns also 1 (true). All the above tests are case-sensitive.
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
- 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
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
Rust
Comparisons are case sensitive by default, all (Ascii) uppercase letters are treated as lexically before all lowercase letters. For case-insensitive comparisons, use Ascii Extensions. In general, case is not a concept that applies to all unicode symbols.
use std::ascii::AsciiExt; // for case insensitives only
fn main() {
// only same types can be compared
// String and String or &str and &str
// exception: strict equality and inequality also work on &str and String
let a: &str = "abc";
let b: String = "Bac".to_owned();
// Strings are coerced to &str when borrowed and needed
if a == b { println!("The strings are equal") }
if a != b { println!("The strings are not equal") }
if a > &b { println!("The first string is lexically after the second") }
if a < &b { println!("The first string is lexically before the second") }
if a >= &b { println!("The first string is not lexically before the second") }
if a <= &b { println!("The first string is not lexically after the second") }
// case-insensitives:
// equality
// this avoids new allocations
if a.eq_ignore_ascii_case(&b) { println!("Both strings are equal when ignoring case") }
// everything else, create owned Strings, then compare as above
let a2 = a.to_ascii_uppercase();
let b2 = b.to_ascii_uppercase();
// repeat checks
}
- Output:
The strings are not equal The first string is lexically after the second The first string is not lexically before the second
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á")
}
- 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
;; 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")
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.
$ 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;
The function below compares strings, which may contain digit sequences. The digit sequences are compared numerically.
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;
Original source: [2]
Sidef
var methods = %w(== != > >= < <= <=>)
for s1, s2 in [<YUP YUP>,<YUP Yup>,<bot bat>,<aaa zz>] {
methods.each{|m| "%s %s %s\t%s\n".printf(s1, m, s2, s1.(m)(s2))}
print "\n"
}
Smalltalk
methods := #(= ~= > >= < <= sameAs: ).
#(
('YUP' 'YUP')
('YUP' 'yup')
) pairsDo:[:s1 :s2 |
methods do:[:m |
'%-20s\t%s\n' printf:
{
('(%S %s %S)' printf:{s1 . m . s2}) .
(s1 perform:m with:s2)
} on:Stdout
].
Stdout cr
]
- Output:
('YUP' = 'YUP') true ('YUP' ~= 'YUP') false ('YUP' > 'YUP') false ('YUP' >= 'YUP') true ('YUP' < 'YUP') false ('YUP' <= 'YUP') true ('YUP' sameAs: 'YUP') true ('YUP' = 'yup') false ('YUP' ~= 'yup') true ('YUP' > 'yup') false ('YUP' >= 'yup') false ('YUP' < 'yup') true ('YUP' <= 'yup') true ('YUP' sameAs: 'yup') true
SNOBOL4
s1 = 'mnopqrs'
s2 = 'mnopqrs'
s3 = 'mnopqr'
s4 = 'nop'
s5 = 'nOp'
OUTPUT = 'Case sensitive comparisons:'
OUTPUT = LEQ(s1, s2) s1 ' and ' s2 ' are equal (LEQ).'
OUTPUT = IDENT(s1, s2) s1 ' and ' s2 ' are equal (IDENT).'
OUTPUT =
OUTPUT = LNE(s1, s3) s1 ' and ' s3 ' are not equal (LNE).'
OUTPUT = ~LEQ(s1, s3) s1 ' and ' s3 ' are not equal (~LEQ).'
OUTPUT = DIFFER(s1, s3) s1 ' and ' s3 ' are not equal (DIFFER).'
OUTPUT =
OUTPUT = LGE(s1, s3) s1 ' is greater than or equal to ' s3 ' (LGE).'
OUTPUT = LLE(s3, s1) s3 ' is less than or equal to ' s1 ' (LLE).'
OUTPUT =
OUTPUT = LGT(s4, s1) s4 ' is greater than ' s1 ' (LGT).'
OUTPUT = LLT(s1, s4) s1 ' is less than ' s4 ' (LLT).'
OUTPUT =
OUTPUT = "Case insensitive comparison:"
OUTPUT = LEQ(s4, REPLACE(s5, &UCASE, &LCASE)) s4 ' and ' s5 ' are equal.'
OUTPUT =
OUTPUT = 'String and numeric conversions and comparisons:'
OUTPUT = EQ('1234', 1234) '"1234" and 1234 are equal (coerce to integer).'
OUTPUT = LEQ('1234', 1234) '"1234" and 1234 are equal (coerce to string).'
OUTPUT =
OUTPUT = GT('1234', 1233) '"1234" is greater than 1233 (numeric comparison).'
OUTPUT = LT('1233', 1234) '"1233" is less than 1234 (numeric comparison).'
END
- Output:
Case sensitive comparisons: mnopqrs and mnopqrs are equal (LEQ). mnopqrs and mnopqrs are equal (IDENT). mnopqrs and mnopqr are not equal (LNE). mnopqrs and mnopqr are not equal (~LEQ). mnopqrs and mnopqr are not equal (DIFFER). mnopqrs is greater than or equal to mnopqr (LGE). mnopqr is less than or equal to mnopqrs (LLE). nop is greater than mnopqrs (LGT). mnopqrs is less than nop (LLT). Case insensitive comparison: nop and nOp are equal. String and numeric conversions and comparisons: "1234" and 1234 are equal (coerce to integer). "1234" and 1234 are equal (coerce to string). "1234" is greater than 1233 (numeric comparison). "1233" is less than 1234 (numeric comparison).
Standard ML
map String.compare [ ("one","one"),
("one","two"),
("one","Two"),
("one",String.map Char.toLower "Two")
] ;
val it = [EQUAL, LESS, GREATER, LESS]: order list
"one" <> "two" ;
val it = true: bool
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")
- Output:
'cat' and 'dog' are not lexically equal. 'cat' is lexically before 'dog'. 'cat' is not lexically after 'dog'.
Tailspin
$a -> \(when <=$b> do '$a; equals $b;' ! \) -> !OUT::write
$a -> \(when <~=$b> do '$a; not equal to $b;' ! \) -> !OUT::write
$a -> \(when <..$b> do '$a; lexically less or equal to $b;' ! \) -> !OUT::write
$a -> \(when <$b..> do '$a; lexically greater or equal to $b;' ! \) -> !OUT::write
$a -> \(when <..~$b> do '$a; lexically less than $b;' ! \) -> !OUT::write
$a -> \(when <$b~..> do '$a; lexically greater than $b;' ! \) -> !OUT::write
$a -> \(when <'$b;'> do '$a; matches the regex $b;' ! \) -> !OUT::write
$a -> \(when <'(?i)$b;'> do '$a; matches the regex $b; case insensitively' ! \) -> !OUT::write
Tcl
The best way to compare two strings in Tcl for equality is with the eq
and ne
expression operators:
if {$a eq $b} {
puts "the strings are equal"
}
if {$a ne $b} {
puts "the strings are not equal"
}
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):
if {[string compare $a $b] < 0} {
puts "first string lower than second"
}
if {[string compare $a $b] > 0} {
puts "first string higher than second"
}
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:
if {[string equal -length 3 $x "abc123"]} {
puts "first three characters are equal"
}
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.
#!/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.
Bash and other POSIX shells do support lexical comparisons:
#!/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
- 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
Vala
void main() {
var s1 = "The quick brown";
var s2 = "The Quick Brown";
stdout.printf("== : %s\n", s1 == s2 ? "true" : "false");
stdout.printf("!= : %s\n", s1 != s2 ? "true" : "false");
stdout.printf("< : %s\n", s1 < s2 ? "true" : "false");
stdout.printf("<= : %s\n", s1 <= s2 ? "true" : "false");
stdout.printf("> : %s\n", s1 > s2 ? "true" : "false");
stdout.printf(">= : %s\n", s1 >= s2 ? "true" : "false");
}
- Output:
== : false != : true < : false <= : false > : true >= : true
V (Vlang)
fn main() {
c := "cat"
d := "dog"
if c == d {
println('$c is bytewise identical to $d')
}
if c != d {
println('$c is bytewise different from $d')
}
if c > d {
println('$c is lexically bytewise greater than $d')
}
if c < d {
println('$c is lexically bytewise less than $d')
}
if c >= d {
println('$c is lexically bytewise greater than or equal to $d')
}
if c <= d {
println('$c is lexically bytewise less than or equal to $d')
}
}
- Output:
cat is bytewise different from dog cat is lexically bytewise less than dog cat is lexically bytewise less than or equal to dog
WDTE
== 'example1' 'example2' -- io.writeln io.stdout; # Test for exact equality.
== 'example1' 'example2' -> ! -- io.writeln io.stdout; # Test for inequality.
< 'example1' 'example2' -- io.writeln io.stdout; # Test for lexical before.
> 'example1' 'example2' -- io.writeln io.stdout; # Test for lexical after.
# Case insensitive equality check by converting both to lowercase.
let str => import 'strings';
== (str.lower 'eXaMpLe') (str.lower 'ExAmPlE') -- io.writeln io.stdout;
# This is false. Strings are not coerced to numbers and vice-versa.
== '3' 3 -- io.writeln io.stdout;
Wren
The only string comparisons built into the language itself are equality and inequality. However, the above module enables us to do full lexicographical comparisons of any strings, including numeric strings, by comparing their corresponding Unicode codepoints.
Case insensitive comparisons can be achieved by converting both strings to the same case before the comparisons are made.
import "./str" for Str
var compareStrings = Fn.new { |a, b, sens|
System.write("Comparing '%(a)' and '%(b)', ")
var c
var d
if (sens) {
System.print("case sensitively:")
c = a
d = b
} else {
System.print("case insensitively:")
c = Str.lower(a)
d = Str.lower(b)
}
System.print(" %(a) < %(b) -> %(Str.lt(c, d))")
System.print(" %(a) > %(b) -> %(Str.gt(c, d))")
System.print(" %(a) == %(b) -> %(c == d)")
System.print(" %(a) != %(b) -> %(c != d)")
System.print(" %(a) <= %(b) -> %(Str.le(c, d))")
System.print(" %(a) >= %(b) -> %(Str.ge(c, d))")
System.print()
}
compareStrings.call("cat", "dog", true)
compareStrings.call("Rat", "RAT", true)
compareStrings.call("Rat", "RAT", false)
compareStrings.call("1100", "200", true)
- Output:
Comparing 'cat' and 'dog', case sensitively: cat < dog -> true cat > dog -> false cat == dog -> false cat != dog -> true cat <= dog -> true cat >= dog -> false Comparing 'Rat' and 'RAT', case sensitively: Rat < RAT -> false Rat > RAT -> true Rat == RAT -> false Rat != RAT -> true Rat <= RAT -> false Rat >= RAT -> true Comparing 'Rat' and 'RAT', case insensitively: Rat < RAT -> false Rat > RAT -> false Rat == RAT -> true Rat != RAT -> false Rat <= RAT -> true Rat >= RAT -> true Comparing '1100' and '200', case sensitively: 1100 < 200 -> true 1100 > 200 -> false 1100 == 200 -> false 1100 != 200 -> true 1100 <= 200 -> true 1100 >= 200 -> false
XPL0
include xpllib; \provides StrLen, ToLower, StrCopy, and StrCmp
proc StrToLower(A, B);
char A, B, I;
for I:= 0 to StrLen(B) do A(I):= ToLower(B(I));
proc CompareStrings(A, B, Sens);
char A, B, Sens, C, D;
[C:= Reserve(StrLen(A)+1);
D:= Reserve(StrLen(B)+1);
Text(0, "Comparing "); Text(0, A); Text(0, " and "); Text(0, B); Text(0, ", ");
if Sens then
[Text(0, "case sensitively:^m^j");
StrCopy(C, A);
StrCopy(D, B);
]
else [Text(0, "case insensitively:^m^j");
StrToLower(C, A);
StrToLower(D, B);
];
Text(0, " "); Text(0, A); Text(0, " < "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) < 0 then "true" else "false"); CrLf(0);
Text(0, " "); Text(0, A); Text(0, " > "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) > 0 then "true" else "false"); CrLf(0);
Text(0, " "); Text(0, A); Text(0, " = "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) = 0 then "true" else "false"); CrLf(0);
Text(0, " "); Text(0, A); Text(0, " # "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) # 0 then "true" else "false"); CrLf(0);
Text(0, " "); Text(0, A); Text(0, " <= "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) <= 0 then "true" else "false"); CrLf(0);
Text(0, " "); Text(0, A); Text(0, " >= "); Text(0, B); Text(0, " -> ");
Text(0, if StrCmp(C, D) >= 0 then "true" else "false"); CrLf(0);
CrLf(0);
];
[CompareStrings("cat", "dog", true);
CompareStrings("Rat", "RAT", true);
CompareStrings("Rat", "RAT", false);
CompareStrings("1100", "200", true);
]
- Output:
Comparing cat and dog, case sensitively: cat < dog -> true cat > dog -> false cat = dog -> false cat # dog -> true cat <= dog -> true cat >= dog -> false Comparing Rat and RAT, case sensitively: Rat < RAT -> false Rat > RAT -> true Rat = RAT -> false Rat # RAT -> true Rat <= RAT -> false Rat >= RAT -> true Comparing Rat and RAT, case insensitively: Rat < RAT -> false Rat > RAT -> false Rat = RAT -> true Rat # RAT -> false Rat <= RAT -> true Rat >= RAT -> true Comparing 1100 and 200, case sensitively: 1100 < 200 -> true 1100 > 200 -> false 1100 = 200 -> false 1100 # 200 -> true 1100 <= 200 -> true 1100 >= 200 -> false
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
- Programming Tasks
- Basic Data Operations
- Basic language learning
- Simple
- 11l
- AArch64 Assembly
- Action!
- Ada
- Aime
- ALGOL 68
- ALGOL W
- Apex
- AppleScript
- ARM Assembly
- Arturo
- Astro
- Avail
- AutoHotkey
- AWK
- BASIC
- Applesoft BASIC
- BASIC256
- BBC BASIC
- QBasic
- True BASIC
- Yabasic
- UBasic/4tH
- Bracmat
- Burlesque
- C
- C++
- Clipper
- Clojure
- COBOL
- ColdFusion
- Common Lisp
- Component Pascal
- D
- Delphi
- SysUtils,StdCtrls
- DuckDB
- Dyalect
- EasyLang
- Ecstasy
- Ed
- Elena
- Elixir
- EMal
- Erlang
- F Sharp
- Factor
- Falcon
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Go
- Harbour
- Haskell
- Icon
- Unicon
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Lasso
- Lingo
- Lua
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- MiniScript
- Nanoquery
- NetRexx
- Nim
- Oforth
- OoRexx
- PARI/GP
- Perl
- Phix
- Phix/basics
- Phixmonti
- Picat
- PicoLisp
- PowerShell
- PureBasic
- Python
- QB64
- Quackery
- R
- Racket
- Raku
- Relation
- REXX
- Ring
- Robotic
- RPL
- Ruby
- Run BASIC
- Rust
- Scala
- Scheme
- Seed7
- Sidef
- Smalltalk
- SNOBOL4
- Standard ML
- Swift
- Tailspin
- Tcl
- UNIX Shell
- Vala
- V (Vlang)
- WDTE
- Wren
- Wren-str
- XPL0
- Zkl
- Bc/Omit
- Brlcad/Omit
- Dc/Omit
- GUISS/Omit
- Lilypond/Omit
- Openscad/Omit