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


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")
}

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")
}

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


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
}

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 
}

7

Możesz po prostu rzucić własne:

func equalIgnoringCase(a:String, b:String) -> Bool {
    return a.lowercaseString == b.lowercaseString
}

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)
}

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")
}

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")
}

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

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
    } 
}

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")
}


-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'

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"))

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")
}

2
Twoje rozwiązanie jest nieprawidłowe. Rozważ łańcuchy „casha” i „cash”
clarkcox3,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.