Jak porównać dwa ciągi ignorujące wielkość liter w języku Swift?

97

Jak możemy porównać dwa ciągi w szybkim ignorowaniu przypadku? na przykład:

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

Czy istnieje metoda, która zwróci wartość true, jeśli porównamy var a & var b

ak_tyagi
źródło
1
Przed porównaniem możesz zamienić oba na małe litery.
Dino Tw
9
Wystarczy zauważyć, lowercaseStringże jest to wymienione w niektórych odpowiedziach w niektórych językach (na przykład Straße! = STRASSE)
Alladinian
@Alladinian, jak byś to zaproponował. Większość przykładów rozwiązania tego problemu pokazuje konwersję na wszystkie wielkie lub małe litery?
Steve
5
@Steve Apple sugeruje caseInsensitiveCompare:& localizedCaseInsensitiveCompare:zamiast tego
Alladinian
3
@Steve Sure! (możesz spróbować "Straße".localizedCaseInsensitiveCompare("STRASSE")- Pamiętaj, aby zaimportować Foundation)
Alladinian

Odpowiedzi:

14

Spróbuj tego:

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)

wynik jest typem wyliczenia NSComparisonResult:

enum NSComparisonResult : Int {

    case OrderedAscending
    case OrderedSame
    case OrderedDescending
}

Możesz więc użyć instrukcji if:

if result == .OrderedSame {
    println("equal")
} else {
    println("not equal")
}
Greg
źródło
Jeśli dobrze pamiętam, parametry range i locale są opcjonalne i można je całkowicie pominąć.
Mick MacCallum
3
Tak, chciałem pokazać całą metodę ze wszystkimi parametrami.
Greg
Powinieneś tu znaleźć właściwą odpowiedź. Porównywanie strun to nie tylko wiedza, czy są równe, czy nie
Mikael
184

Spróbuj tego :

Dla starszych jerzyków:

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

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

Swift 3+

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

if(a.caseInsensitiveCompare(b) == .orderedSame){
    print("voila")
}
iAnurag
źródło
13
W Swift 3 musisz użyća.caseInsensitiveCompare(b) == ComparisonResult.orderedSame
azhidkov
3
Uwaga: caseInsensitiveCompare(_:)nie jest uwzględniony w Swift Standard Library, jest raczej częścią Foundationstruktury, a zatem wymaga import Foundation.
chrisamanse
Czy jest jakiś powód, dla którego jest to lepsze niż a.lowercased() == b.lowercased()?
jowie
@jowie, jak wspomniano w innych komentarzach, użycie małych / dużych liter () może się nie powieść w niektórych językach.
cumanzor
36

Użyj caseInsensitiveComparemetody:

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

CompareResult informuje, które słowo występuje wcześniej niż inne w kolejności leksykograficznej (tj. Które z nich jest bliżej początku słownika). .orderedSameoznacza, że ​​łańcuchy znajdą się w tym samym miejscu w słowniku

Sergey Kalinichenko
źródło
co to .orderedSameznaczy W docs tylko powiedzieć Oba argumenty są równe . Ale dlaczego użyto tutaj słowa „porządek”? Czy jest jakaś sekwencja czy coś? A co robi Lewy operand jest mniejszy niż prawy operand. ( .orderedAscending) średnia dla smyczków
Honey
1
@ Wynik porównania miodu informuje, które słowo występuje wcześniej niż inne w kolejności leksykograficznej (tj. Które z nich jest bliżej początku słownika). .orderedSameoznacza, że ​​łańcuchy trafiłyby do tego samego miejsca w słowniku.
Sergey Kalinichenko
1
@Honey .orderedSameto skrót od ComparisonResult.orderSame... nie musisz nazywać typu, ponieważ kompilator wie, że caseInsensitiveComparezwraca plik ComparisonResult. „Te dwa operandy są równe” - są równe zgodnie z określoną kolejnością… oczywiście „gotówka” i „gotówka” nie są identycznymi ciągami znaków. - Ale dlaczego użyto tutaj słowa „kolejność”? - bo to wynik uporządkowanego porównania. Pozostałe wartości to orderedAscendingi orderedDescending... to nie jest tylko kwestia tego samego lub innego. Jeśli chodzi o „mniejsze”: łańcuchy są jak liczby w dużej bazie.
Jim Balter,
1
Czuję, że to okropny projekt API. Podpis nie jest łatwy do odczytania ... Dzięki temu a.caseInsensitiveCompare(b, comparing: .orderedSame)byłby bardziej czytelny ...
Kochanie,
25
if a.lowercaseString == b.lowercaseString {
    //Strings match
}
Steve
źródło
2
Pure Swift to droga do tego. Nie ma potrzeby podkładania.
Alexander - Przywróć Monikę
2
Konwertowanie wielkości liter, a następnie porównywanie jest nieprawidłowe. Zobacz komentarze pod pytaniem.
Jim Balter
1
@JimBalter Nie powiedziałbym, że to „źle”, ponieważ odpowiada przykładowi podanemu w pytaniu OP. Dla tych z nas, którzy nie potrzebują obsługi lokalizacji, jest to znacznie czystsze!
toddg
4
^ Nie, to źle. Na przykład to, że coś działa, nie ma znaczenia. Ten hack wcale nie jest „czystszy”. Zaakceptowana odpowiedź daje prawidłowe, czyste rozwiązanie.
Jim Balter,
8

WŁAŚCIWA DROGA:

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

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

Uwaga: CompareResult.orderedSame można również zapisać jako .orderedSame w skrócie.

INACZEJ:

za.

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

b.

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

do.

if a.capitalized() == b.capitalized() {
    //Strings match 
}
Saurabh Bhatia
źródło
7

Możesz po prostu rzucić własne:

func equalIgnoringCase(a:String, b:String) -> Bool {
    return a.lowercaseString == b.lowercaseString
}
matowe
źródło
3
Konwertowanie wielkości liter, a następnie porównywanie jest nieprawidłowe. Zobacz komentarze pod pytaniem.
Jim Balter,
7

localizedCaseInsensitiveContains : zwraca, czy odbiornik zawiera dany ciąg, wykonując wyszukiwanie bez uwzględniania wielkości liter i uwzględniające ustawienia regionalne

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

Edytowano :

caseInsensitiveCompare : Zwraca wynik wywołania porównania (_: options :) z NSCaseInsensitiveSearch jako jedyną opcją.

if a.caseInsensitiveCompare(b) == .orderedSame {
    //returns true if a equals b (case insensitive)
}
cgeek
źródło
1
Pytanie dotyczy porównania, a nie ograniczenia.
Jim Balter
Jeśli „a zawiera b” i „b zawiera a” , są one równe. Jest to więc z pewnością możliwe rozwiązanie, nawet jeśli może nie być najbardziej efektywne.
Philipp Maurer
1

Możesz także uczynić wszystkie litery dużymi (lub małymi) i sprawdzić, czy są takie same.

var a = “Cashvar b = “CAShif a.uppercaseString == b.uppercaseString{
  //DO SOMETHING
}

Spowoduje to, że obie zmienne ”CASH”będą takie same, a zatem będą równe.

Możesz także zrobić Stringrozszerzenie

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

if "Something ELSE".equalsIgnoreCase("something Else"){
  print("TRUE")
}
milo526
źródło
3
Konwertowanie wielkości liter, a następnie porównywanie jest nieprawidłowe. Zobacz komentarze pod pytaniem.
Jim Balter
1

Przykład porównania numerów telefonów; używając 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")
}
ikbal
źródło
0

Swift 4, poszedłem na ścieżkę rozszerzenia String, używając caseInsensitiveCompare () jako szablonu (ale pozwalając, aby operand był opcjonalny). Oto plac zabaw, na którym go składałem (nowość w Swift, więc opinie są mile widziane).

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
William T. Mallard
źródło
2
Możesz po prostu użyć .orderedSamezamiast ComparisonResult.orderedSame.
Jim Balter
0

Możesz po prostu napisać rozszerzenie ciągu do porównania w zaledwie kilku wierszach kodu

extension String {

    func compare(_ with : String)->Bool{
        return self.caseInsensitiveCompare(with) == .orderedSame
    } 
}
Mujahid Latif
źródło
0

Dla Swift 5 Zignorowanie wielkości liter i porównanie dwóch ciągów

var a = "cash"
var b = "Cash"
if(a.caseInsensitiveCompare(b) == .orderedSame){
     print("Ok")
}
M Murteza
źródło
-1

Szybki 3

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

}
DoubleK
źródło
2
To jest źle. Zobacz komentarze pod pytaniem.
Jim Balter
-1

Swift 3 : Możesz zdefiniować własnego operatora, np ~=.

infix operator ~=

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

Które możesz następnie wypróbować na placu zabaw

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

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

test() // prints 'same'
Sajjon
źródło
Nie zgodziłem się z tym, ale zauważ, że jest to ogólnie dość zły pomysł, ponieważ powyższy niestandardowy operator dopasowywania wzorców będzie miał pierwszeństwo przed natywnym dopasowywaniem wzorców zwykle używanym podczas dopasowywania Stringwystąpień do siebie (lub do innych Stringliterałów). Wyobraźmy sobie, let str = "isCAMELcase"są przełączane, w przypadku następująco: case "IsCamelCase": ... . W przypadku powyższej metody casezostanie to wprowadzone pomyślnie, czego nie oczekuje się w przypadku standardowej implementacji Stringdopasowania wzorców w bibliotekach . Zaktualizowana odpowiedź Swift 3 jest jednak nadal dobra, ale ...
dfrib
... rozważ użycie funkcji niestandardowej (lub Stringrozszerzenia) jako pomocnika powyżej zamiast nadpisywania domyślnego Stringdopasowania wzorców.
dfrib
-1
extension String
{
    func equalIgnoreCase(_ compare:String) -> Bool
    {
        return self.uppercased() == compare.uppercased()
    }
}

próbka użycia

print("lala".equalIgnoreCase("LALA"))
print("l4la".equalIgnoreCase("LALA"))
print("laLa".equalIgnoreCase("LALA"))
print("LALa".equalIgnoreCase("LALA"))
luhuiya
źródło
1
To nie działa w przypadku niektórych ciągów znaków w niektórych językach ... zobacz komentarze pod pytaniem i wiele poprawnych odpowiedzi, z których niektóre - w tym zaakceptowana - poprzedziły twoje o lata.
Jim Balter,
-2

Swift 3:

Możesz również użyć zlokalizowanego porównania bez rozróżniania wielkości liter między dwoma funkcjami ciągów i zwraca Bool

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

if a.localizedCaseInsensitiveContains(b) {
    print("Identical")           
} else {
    print("Non Identical")
}
Kegham K.
źródło
2
Twoje rozwiązanie jest nieprawidłowe. Rozważ łańcuchy „casha” i „cash”
clarkcox3,