How to compare two strings ignoring case in Swift language?
Asked Answered
P

17

115

How can we compare two strings in swift ignoring case ? for eg :

var a = "Cash"
var b = "cash"

Is there any method that will return true if we compare var a & var b

Pricefixing answered 29/5, 2015 at 14:53 Comment(6)
You could convert both to lower case before doing comparison.Metaphor
Just to note that lowercaseString that is mentioned in some answers will fail in some languages (Straße != STRASSE for example)Hydrosome
@Hydrosome how would you suggest doing it then. Most examples to solve this issue show converting to either all upper case or all lower case?Literally
@Literally Apple suggests caseInsensitiveCompare: & localizedCaseInsensitiveCompare: insteadHydrosome
@Hydrosome thank you, do those handle your example as well?Literally
@Literally Sure! (you can try "Straße".localizedCaseInsensitiveCompare("STRASSE") - Remember to import Foundation)Hydrosome
M
18

Try this:

var a = "Cash"
var b = "cash"
let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil, locale: nil)

// You can also ignore last two parameters(thanks 0x7fffffff)
//let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch)

result is type of NSComparisonResult enum:

enum NSComparisonResult : Int {

    case OrderedAscending
    case OrderedSame
    case OrderedDescending
}

So you can use if statement:

if result == .OrderedSame {
    println("equal")
} else {
    println("not equal")
}
Manmade answered 29/5, 2015 at 14:57 Comment(3)
If I recall correctly, the range and locale parameters are optional and can be omitted entirely.Edwinaedwine
Yes indeed, I wanted to show whole method with all of the parameters.Manmade
You should have the right answer here. Comparing strings is not only about knowing if they are equal or notJonette
A
204

Try this :

For older swift:

var a : String = "Cash"
var b : String = "cash"

if(a.caseInsensitiveCompare(b) == NSComparisonResult.OrderedSame){
    println("Et voila")
}

Swift 3+

var a : String = "Cash"
var b : String = "cash"
    
if(a.caseInsensitiveCompare(b) == .orderedSame){
    print("Et voila")
}
Almondeyed answered 29/5, 2015 at 15:6 Comment(5)
In Swift 3 you need to use a.caseInsensitiveCompare(b) == ComparisonResult.orderedSameRotor
Note: caseInsensitiveCompare(_:) is not included in the Swift Standard Library, rather it is part of the Foundation framework, thus, requiring import Foundation.Repugnance
Is there any reason why this is any better than a.lowercased() == b.lowercased() ?Bernadettebernadina
@Bernadettebernadina as mentioned in the other comments, using lower/uppercased() may fail on certain languages.Splenic
a.localizedStandardRange(of: b) == a.startIndex..<a.endIndex seems to work better for me and supports localization. The above code doesn’t work for all languages (case rules may differ). Also all localized*Compare() return false if a = "Et voila" and b = "Et voilà", when it should be true.Frig
C
42

Use caseInsensitiveCompare method:

let a = "Cash"
let b = "cash"
let c = a.caseInsensitiveCompare(b) == .orderedSame
print(c) // "true"

ComparisonResult tells you which word comes earlier than the other in lexicographic order (i.e. which one comes closer to the front of a dictionary). .orderedSame means the strings would end up in the same spot in the dictionary

Combo answered 29/5, 2015 at 15:5 Comment(4)
what does .orderedSame mean? The docs just say The two operands are equal. But why is the word 'order' used here? Is there a sequence or something? And what does The left operand is smaller than the right operand. (.orderedAscending) mean for stringsPellet
@Honey Comparison result tells you which word comes earlier than the other in lexicographic order (i.e. which one comes closer to the front of a dictionary). .orderedSame means the strings would end up in the same spot in the dictionary.Combo
@Honey .orderedSame is short for ComparisonResult.orderSame ... you don't have to name the type since the compiler knows that caseInsensitiveCompare returns a ComparisonResult. "The two operands are equal" -- they are equal according to a specific ordering ... clearly, "Cash" and "cash" are not identical string values. "But why is the word 'order' used here?" -- because it's the result of an ordered comparison. The other values are orderedAscending and orderedDescending ... it's not just a question of same or different. As for "smaller": strings are like numbers in a large base.Quenby
I feel like this is terrible API design. The signature is not easy to read...Making it a.caseInsensitiveCompare(b, comparing: .orderedSame) would have been more readable...Pellet
L
27
if a.lowercaseString == b.lowercaseString {
    //Strings match
}
Literally answered 29/5, 2015 at 15:0 Comment(4)
Pure Swift is the way to go here. No need for foundation.Od
Converting case and then comparing is wrong. See the comments under the question.Quenby
@JimBalter I wouldn't say it's "wrong" since it answers the example given in the OP's question. For those of us who don't need to support localization this is much cleaner!Metatherian
^ No, it's wrong. That something happens to work for one example is irrelevant. This hack is not "cleaner" at all. The accepted answer gives the correct, clean solution.Quenby
M
18

Try this:

var a = "Cash"
var b = "cash"
let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil, locale: nil)

// You can also ignore last two parameters(thanks 0x7fffffff)
//let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch)

result is type of NSComparisonResult enum:

enum NSComparisonResult : Int {

    case OrderedAscending
    case OrderedSame
    case OrderedDescending
}

So you can use if statement:

if result == .OrderedSame {
    println("equal")
} else {
    println("not equal")
}
Manmade answered 29/5, 2015 at 14:57 Comment(3)
If I recall correctly, the range and locale parameters are optional and can be omitted entirely.Edwinaedwine
Yes indeed, I wanted to show whole method with all of the parameters.Manmade
You should have the right answer here. Comparing strings is not only about knowing if they are equal or notJonette
D
13

localizedCaseInsensitiveContains : Returns whether the receiver contains a given string by performing a case-insensitive, locale-aware search

if a.localizedCaseInsensitiveContains(b) {
    //returns true if a contains b (case insensitive)
}

Edited:

caseInsensitiveCompare : Returns the result of invoking compare(_:options:) with NSCaseInsensitiveSearch as the only option.

if a.caseInsensitiveCompare(b) == .orderedSame {
    //returns true if a equals b (case insensitive)
}
Delaryd answered 5/3, 2018 at 5:2 Comment(2)
The question is about comparison, not containment.Quenby
If "a contains b" and "b contains a", they are equal. So this is surely a possible solution, even if it may not be the most effective one.Blob
X
10

CORRECT WAY:

let a: String = "Cash"
let b: String = "cash"

if a.caseInsensitiveCompare(b) == .orderedSame {
    //Strings match 
}

Please note: ComparisonResult.orderedSame can also be written as .orderedSame in shorthand.

OTHER WAYS:

a.

if a.lowercased() == b.lowercased() {
    //Strings match 
}

b.

if a.uppercased() == b.uppercased() {
    //Strings match 
}

c.

if a.capitalized() == b.capitalized() {
    //Strings match 
}
Xerxes answered 8/5, 2017 at 17:3 Comment(0)
P
6

Could just roll your own:

func equalIgnoringCase(a:String, b:String) -> Bool {
    return a.lowercaseString == b.lowercaseString
}
Paramagnetism answered 29/5, 2015 at 14:59 Comment(1)
Converting case and then comparing is wrong. See the comments under the question.Quenby
V
2

Phone numbers comparison example; using swift 4.2

var selectPhone = [String]()

if selectPhone.index(where: {$0.caseInsensitiveCompare(contactsList[indexPath.row].phone!) == .orderedSame}) != nil {
    print("Same value")
} else {
    print("Not the same")
}
Vladamar answered 2/10, 2018 at 18:2 Comment(0)
A
1

You can just write your String Extension for comparison in just a few line of code

extension String {

    func compare(_ with : String)->Bool{
        return self.caseInsensitiveCompare(with) == .orderedSame
    } 
}
Agony answered 8/5, 2019 at 6:41 Comment(0)
S
1

For Swift 5 Ignoring the case and compare two string

var a = "cash"
var b = "Cash"
if(a.caseInsensitiveCompare(b) == .orderedSame){
     print("Ok")
}
Sachiko answered 15/6, 2019 at 2:24 Comment(1)
This duplicates many previous answers.Chesser
K
0

Swift 4, I went the String extension route using caseInsensitiveCompare() as a template (but allowing the operand to be an optional). Here's the playground I used to put it together (new to Swift so feedback more than welcome).

import UIKit

extension String {
    func caseInsensitiveEquals<T>(_ otherString: T?) -> Bool where T : StringProtocol {
        guard let otherString = otherString else {
            return false
        }
        return self.caseInsensitiveCompare(otherString) == ComparisonResult.orderedSame
    }
}

"string 1".caseInsensitiveEquals("string 2") // false

"thingy".caseInsensitiveEquals("thingy") // true

let nilString1: String? = nil
"woohoo".caseInsensitiveEquals(nilString1) // false
Khiva answered 23/1, 2018 at 0:1 Comment(1)
You can just use .orderedSame rather than ComparisonResult.orderedSame.Quenby
H
0

Created an extension function for it. Pass caseSensitive as false if you want case insensitive compare.

extension String {
    
    func equals(to string: String, caseSensitive: Bool = true) -> Bool {
        if caseSensitive {
            return self.compare(string) == .orderedSame
        } else {
            return self.caseInsensitiveCompare(string) == .orderedSame
        }
    }
}

Example:

"cash".equals(to: "Cash", caseSensitive: false) //returns true
"cash".equals(to: "Cash") //returns false
Higginson answered 14/5, 2023 at 6:36 Comment(0)
H
-1

Swift 3: You can define your own operator, e.g. ~=.

infix operator ~=

func ~=(lhs: String, rhs: String) -> Bool {
   return lhs.caseInsensitiveCompare(rhs) == .orderedSame
}

Which you then can try in a playground

let low = "hej"
let up = "Hej"

func test() {
    if low ~= up {
        print("same")
    } else {
        print("not same")
    }
}

test() // prints 'same'
Huihuie answered 2/12, 2016 at 17:35 Comment(2)
I didn't downvote this, but note that this is generally a quite bad idea, since the custom pattern matching operator above will take precedence over the native pattern matching usually used when matching String instances to eachother (or to other String literals). Imagine let str = "isCAMELcase" being switched over, with a case as follows: case "IsCamelCase": ... . With the method above, this case would be entered successfully, which is not expected coming from the standard libs implementation of String pattern matching. An updated Swift 3 answer is still good though, but ...Footwear
... consider using a custom function (or String extension) as helper above rather than overriding the default String pattern matching.Footwear
G
-2

You could also make all the letters uppercase (or lowercase) and see if they are the same.

var a = “Cash”
var b = “CASh”

if a.uppercaseString == b.uppercaseString{
  //DO SOMETHING
}

This will make both variables as ”CASH” and thus they are equal.

You could also make a String extension

extension String{
  func equalsIgnoreCase(string:String) -> Bool{
    return self.uppercaseString == string.uppercaseString
  }
}

if "Something ELSE".equalsIgnoreCase("something Else"){
  print("TRUE")
}
Gina answered 29/5, 2015 at 15:1 Comment(1)
Converting case and then comparing is wrong. See the comments under the question.Quenby
R
-2

Swift 3

if a.lowercased() == b.lowercased() {

}
Rotarian answered 15/11, 2016 at 10:16 Comment(1)
This is wrong. See the comments under the question.Quenby
C
-3

Swift 3:

You can also use the localized case insensitive comparison between two strings function and it returns Bool

var a = "cash"
var b = "Cash"

if a.localizedCaseInsensitiveContains(b) {
    print("Identical")           
} else {
    print("Non Identical")
}
Commend answered 8/5, 2017 at 16:38 Comment(1)
Your solution is incorrect. Consider the strings "casha" and "Cash"Unfair
B
-3
extension String
{
    func equalIgnoreCase(_ compare:String) -> Bool
    {
        return self.uppercased() == compare.uppercased()
    }
}

sample of use

print("lala".equalIgnoreCase("LALA"))
print("l4la".equalIgnoreCase("LALA"))
print("laLa".equalIgnoreCase("LALA"))
print("LALa".equalIgnoreCase("LALA"))
Brady answered 22/12, 2017 at 6:58 Comment(1)
This doesn't work for some strings in some languages ... see the comments under the question, and the many correct answers, some of which -- including the accepted one -- preceded yours by years.Quenby

© 2022 - 2024 — McMap. All rights reserved.