String comparison: Difference between revisions

(Add Avail entry)
Line 1,120:
? "The strings are equal"
ENDIF
</lang>
 
 
=={{header|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.
 
<lang Clojure>(= "abc" "def") ; false
(= "abc" "abc") ; true
 
(not= "abc" "def") ; true
(not= "abc" "abc") ; false</lang>
 
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.
 
<lang Clojure>(= "abc" "abc" "abc" "abc") ; true
(= "abc" "abc" "abc" "def") ; false</lang>
 
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.
 
<lang Clojure>(apply = ["abc" "abc" "abc" "abc"]) ; true</lang>
 
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'.
 
<lang Clojure>(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")</lang>
 
If want a case-insensitive comparison, you need to up-case or down-case the input strings.
 
<lang Clojure>(defn str-caseless= [a b]
(= (clojure.string/lower-case a)
(clojure.string/lower-case b)))
 
(str-caseless= "foo" "fOO") ; true</lang>
 
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.
 
<lang Clojure>(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</lang>
 
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.
 
<lang Clojure>(def s1 (str "abc" "def"))
(def s2 (str "ab" "cdef"))
 
(= s1 "abcdef") ; true
(= s1 s2) ; true
 
(identical? s1 "abcdef") ; false
(identical? s1 s2) ; false</lang>
 
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.
 
<lang Clojure>(defn istr [s]
(.intern s))
 
(def s3 (istr s1))
(def s4 (istr s2))
 
(= s3 s4) ; true
(identical? s3 s4) ; true
</lang>
 
Anonymous user