Jak sprawdzić, czy ciąg zawiera inny ciąg w Swift?


535

W Objective-Ckodzie, aby sprawdzić podciąg w NSString:

NSString *string = @"hello Swift";
NSRange textRange =[string rangeOfString:@"Swift"];
if(textRange.location != NSNotFound)
{
    NSLog(@"exists");
}

Ale jak to zrobić w Swift?


2
@rckoenes Jestem nowy w swift, wiem, jak to zrobić C
Rajneesh071

1
Dlaczego więc nie założyć placu zabaw i wypróbować go?
rckoenes

Jeśli nadal jesteś w pobliżu, zmień zaakceptowaną odpowiedź na odpowiedź użytkownika1021430 ... jest poprawna
Dan Rosenstark,

Odpowiedzi:


1044

Za pomocą Swift możesz wykonać dokładnie to samo połączenie:

Swift 4 i Swift 5

W Swift 4 String jest zbiorem Characterwartości, nie było tak w Swift 2 i 3, więc możesz użyć tego bardziej zwięzłego kodu 1 :

let string = "hello Swift"
if string.contains("Swift") {
    print("exists")
}

Swift 3.0+

var string = "hello Swift"

if string.range(of:"Swift") != nil { 
    print("exists")
}

// alternative: not case sensitive
if string.lowercased().range(of:"swift") != nil {
    print("exists")
}

Starsze szybkie

var string = "hello Swift"

if string.rangeOfString("Swift") != nil{ 
    println("exists")
}

// alternative: not case sensitive
if string.lowercaseString.rangeOfString("swift") != nil {
    println("exists")
}

Mam nadzieję, że jest to pomocne rozwiązanie, ponieważ niektórzy ludzie, w tym ja, mieli dziwne problemy z telefonowaniem containsString(). 1

PS. Nie zapomnijimport Foundation

Przypisy

  1. Pamiętaj tylko, że korzystanie z funkcji kolekcji w ciągach znaków ma pewne przypadki krawędzi, które mogą dać nieoczekiwane wyniki, np. W przypadku emoji lub innych klastrów grafemów, takich jak litery akcentowane.

13
Dokumentacja Apple mówi: An NSRange structure giving the location and length in the receiver of the first occurrence of aString. Returns {NSNotFound, 0} if aString is not found or is empty (@"").więc może po prostu sprawdzanie nilnie działa poprawnie.
Alex

7
string.lowercaseString.rangeOfString („swift”). location! = NSNotFound. Zapoznaj się z dokumentacją. Nie otrzymasz z powrotem żadnego obiektu zerowego.
TheCodingArt

4
@TheGamingArt Tak, będziesz. Szybkie objazdy w obie strony automagicznie, tak że jeśli NSRange {NSNotFound, 0}jest reprezentowany jako zero. Jeśli jest to rzeczywisty zasięg, jest przedstawiany jako Swift Range (opcjonalnie). Fajne.
mat

4
Grr. zawieraString nie jest w dokumentach, nawet od Xcode 6.3.1.
Duncan C

19
@TheGoonie: To nie dzwoni NSString„s .rangeOfString(). To woła String„s .rangeOfString(), która została zgłoszona jakofunc rangeOfString(aString: String, options mask: NSStringCompareOptions = default, range searchRange: Range<Index>? = default, locale: NSLocale? = default) -> Range<Index>?
newacct

192

Sposób przedłużenia

Szybki 4

extension String {
    func contains(find: String) -> Bool{
        return self.range(of: find) != nil
    }
    func containsIgnoringCase(find: String) -> Bool{
        return self.range(of: find, options: .caseInsensitive) != nil
    }
}

var value = "Hello world"

print(value.contains("Hello")) // true
print(value.contains("bo"))    // false

print(value.containsIgnoringCase(find: "hello"))    // true
print(value.containsIgnoringCase(find: "Hello"))    // true
print(value.containsIgnoringCase(find: "bo"))       // false

Ogólnie Swift 4 zawiera metodę, jednak jest dostępna z iOS 8.0+


Swift 3.1

Możesz napisać rozszerzenie contains:i containsIgnoringCasedlaString

extension String { 

   func contains(_ find: String) -> Bool{
     return self.range(of: find) != nil
   }

   func containsIgnoringCase(_ find: String) -> Bool{
     return self.range(of: find, options: .caseInsensitive) != nil 
   }
 }

Starsza wersja Swift

extension String {

    func contains(find: String) -> Bool{
       return self.rangeOfString(find) != nil
     }

    func containsIgnoringCase(find: String) -> Bool{
       return self.rangeOfString(find, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil
     }
}

Przykład:

var value = "Hello world"

print(value.contains("Hello")) // true
print(value.contains("bo"))    // false

print(value.containsIgnoringCase("hello"))    // true
print(value.containsIgnoringCase("Hello"))    // true
print(value.containsIgnoringCase("bo"))       // false

6
aby zignorować wielkość liter, użyj return self.rangeOfString (find, options: NSStringCompareOptions.CaseInsensitiveSearch)! = zero
masgar

1
Nie jest już konieczne, chyba że nie masz w Foundationpobliżu ... containsStringdziała dobrze.
Dan Rosenstark

5
dla szybkiego 3.0. Przejdź do: rozszerzenie String {func zawiera (find: String) -> Bool {return self.range (of: find)! = Nil} func zawieraIgnoringCase (find: String) -> Bool {return self.range (of: find , opcje: .caseInsensitive)! = zero}}
Michael Shang,

Dla Swift 4 -> rozszerzenie String {func zawiera (find: String) -> Bool {return self.range (of: find)! = Nil} func zawieraIgnoringCase (find: String) -> Bool {return self.range (of: znajdź, opcje: .caseInsensitive)! = zero}}
shokaveli,

50

Z dokumentacji wynika, że ​​wywołanie containsString()ciągu powinno działać:

Typ łańcucha Swift jest płynnie połączony z klasą NSString Foundation. Jeśli pracujesz z frameworkiem Foundation w Cocoa lub Cocoa Touch, cały interfejs API NSString jest dostępny do wywołania dowolnej utworzonej wartości ciągu, oprócz funkcji łańcucha opisanych w tym rozdziale. Możesz także użyć wartości String w dowolnym interfejsie API, który wymaga instancji NSString.

Jednak to nie działa w ten sposób.

Jeśli spróbujesz użyć someString.containsString(anotherString), pojawi się komunikat o błędzie czasu kompilacji'String' does not contain a member named 'containsString' .

Pozostaje ci kilka opcji, z których jedna polega na jawnym zmostkowaniu się Stringz celem C przy użyciu bridgeToObjectiveC()dwóch pozostałych, polegających na jawnym użyciu an, NSStringa ostatnia polega na rzuceniuString doNSString

Łącząc się, uzyskasz:

var string = "hello Swift"
if string.bridgeToObjectiveC().containsString("Swift") {
    println("YES")
}

Po jawnym wpisaniu ciągu jako NSString, uzyskasz:

var string: NSString = "hello Swift"
if string.containsString("Swift") {
    println("YES")
}

Jeśli masz już istniejący String, możesz zainicjować z niego NSString za pomocą NSString (string :):

var string = "hello Swift"
if NSString(string: string).containsString("Swift") {
    println("YES")
}

I na koniec możesz rzucić istniejący Stringna NSStringjak poniżej

var string = "hello Swift"
if (string as NSString).containsString("Swift") {
    println("YES")
}

4
Ostatni przykład (nie próbowałem innych) zawiesza się dla mnie na iOS 7 (urządzenie); Szybkie aplikacje powinny działać poprawnie na iOS 7. Występuje błąd [__NSCFString containsString:]: unrecognized selector sent to instance. Ponadto nie mogę znaleźć metody containsStringw dokumentacji programistów, aby potwierdzić, czy jest ona nowa dla systemu iOS 8.
Jason Leach

Ciekawy. Testowałem to tylko na placu zabaw. Spróbuję później, kiedy będę na komputerze.
Cezar

trzecia i czwarta opcja są jedynymi dozwolonymi przez kompilator. oba
wypadają

38

Inny. Obsługuje opcje dotyczące liter i znaków diakrytycznych.

Swift 3.0

struct MyString {
  static func contains(_ text: String, substring: String,
                       ignoreCase: Bool = true,
                       ignoreDiacritic: Bool = true) -> Bool {

    var options = NSString.CompareOptions()

    if ignoreCase { _ = options.insert(NSString.CompareOptions.caseInsensitive) }
    if ignoreDiacritic { _ = options.insert(NSString.CompareOptions.diacriticInsensitive) }

    return text.range(of: substring, options: options) != nil
  }
}

Stosowanie

MyString.contains("Niels Bohr", substring: "Bohr") // true

iOS 9+

Funkcja niewrażliwa na wielkość liter i znaki diakrytyczne dostępna od iOS 9.

if #available(iOS 9.0, *) {
  "Für Elise".localizedStandardContains("fur") // true
}

31

Począwszy od Xcode 7.1 i Swift 2.1 containsString()działa dla mnie dobrze.

let string = "hello swift"
if string.containsString("swift") {
    print("found swift")
}

Swift 4:

let string = "hello swift"
if string.contains("swift") {
    print("found swift")
}

I przykład Swift 4 bez rozróżniania wielkości liter:

let string = "Hello Swift"
if string.lowercased().contains("swift") {
    print("found swift")
}

Lub używając Stringrozszerzenia bez rozróżniania wielkości liter :

extension String {
    func containsIgnoreCase(_ string: String) -> Bool {
        return self.lowercased().contains(string.lowercased())
    }
}

let string = "Hello Swift"
let stringToFind = "SWIFT"
if string.containsIgnoreCase(stringToFind) {
    print("found: \(stringToFind)")  // found: SWIFT
}
print("string: \(string)")
print("stringToFind: \(stringToFind)")

// console output:
found: SWIFT
string: Hello Swift
stringToFind: SWIFT

3
musisz import Foundation, w przeciwnym razie to nie zadziała.
Andrii Chernenko

Każdy import UIKitz nich import Foundationjest wymagany, przynajmniej w iOS 11 i Swift 4.
Murray Sagal

Ale w tym rozróżniana jest wielkość liter. Jak zrobić porównanie, ignorując wielkość liter. Jak w java String.equalsIgnoreCase (anotherString)?
zulkarnain shah

@zulkarnainshah Dodałem przykład do odpowiedzi.
Murray Sagal

@MurraySagal To wciąż nie rozróżnia wielkich i małych liter. Konwertujesz oryginalny ciąg na małe litery, a następnie porównujesz go jawnie z ciągiem małych liter.
Wykona

22

W Swift 4.2

Posługiwać się

func contains(_ str: String) -> Bool

Przykład

let string = "hello Swift"
let containsSwift = string.contains("Swift")
print(containsSwift) // prints true

4
Pamiętaj, że wymaga to zaimportowania Foundation.
rmaddy

16

> IN SWIFT 3.0

let str = "Hello Swift"
if str.lowercased().contains("Swift".lowercased()) {
    print("String Contains Another String")
} else {
    print("Not Exists")
}

Wynik

String Contains Another String

15

Możesz to zrobić bardzo łatwo w Swift za pomocą kodu:

let string = "hello Swift";
let subString = (string as NSString).containsString("Swift")
if(subString){println("Exist")}

10

Tylko dodatek do odpowiedzi tutaj.

Możesz również wykonać lokalny test bez rozróżniania wielkości liter, używając:

 - (BOOL)localizedCaseInsensitiveContainsString:(NSString *)aString

Przykład:

    import Foundation

    var string: NSString  =  "hello Swift"
   if string.localizedCaseInsensitiveContainsString("Hello") {
    println("TRUE")
}

AKTUALIZACJA

Jest to część Foundation Framework na iOS i Mac OS X 10.10.xi była częścią 10.10 w momencie mojego pierwotnego publikowania.

Wygenerowano dokument: 2014-06-05 12:26:27 -0700 OS X Informacje o wersji Copyright © 2014 Apple Inc. Wszelkie prawa zastrzeżone.

OS X 10.10 Informacje o wersji Cocoa Foundation Framework

NSString ma teraz następujące dwie metody wygody:

- (BOOL)containsString:(NSString *)str;

- (BOOL)localizedCaseInsensitiveContainsString:(NSString *)str;


1
Należy pamiętać, że takie podejście wymaga systemu iOS 8.
Andrew Ebling

9

Oto mój pierwszy dźgnięcie w tym na szybkim placu zabaw. Rozszerzam String, udostępniając dwie nowe funkcje (zawiera i zawieraIgnoreCase)

extension String {
    func contains(other: String) -> Bool{
        var start = startIndex

        do{
            var subString = self[Range(start: start++, end: endIndex)]
            if subString.hasPrefix(other){
                return true
            }

        }while start != endIndex

        return false
    }

    func containsIgnoreCase(other: String) -> Bool{
        var start = startIndex

        do{
            var subString = self[Range(start: start++, end: endIndex)].lowercaseString
            if subString.hasPrefix(other.lowercaseString){
                return true
            }

        }while start != endIndex

        return false
    }
}

Użyj tego w ten sposób

var sentence = "This is a test sentence"
sentence.contains("this")  //returns false
sentence.contains("This")  //returns true
sentence.containsIgnoreCase("this")  //returns true

"This is another test sentence".contains(" test ")    //returns true

Z radością powitam każdą opinię :)


Następny krok: uczyń to ogólną funkcją, która działa na wszystkich kolekcjach :-) Np. Sprawdź wbudowaną funkcję StartWith (). W wariancie „ignoruj ​​przypadek” tylko małe litery należy wpisać tylko raz (pozwól lc = other.lowercaseString przed do)
hnh

9

Ze wszystkich odpowiedzi tutaj, myślę, że albo nie działają, albo są trochę hack (powrót do NSString). Jest bardzo prawdopodobne, że poprawna odpowiedź na to pytanie zmieniła się w zależności od wersji beta.

Oto czego używam:

let string: String = "hello Swift"
if string.rangeOfString("Swift") != nil
{
    println("exists")
}

W wersji Beta 5 wymagane było „! = Zero”.


6

Tu masz:

let s = "hello Swift"
if let textRange = s.rangeOfString("Swift") {
    NSLog("exists")
}

Czasami może być potrzebny kompaktowy formularz w następujący sposób: pozwól rangeIfExists = string.rangeOfString („Swift”) ?? false, który albo zwraca false jako wartość logiczną, jeśli nie jest zawarty, albo NSRange w przeciwnym razie
Stéphane de Luca

5

Nie musisz do tego pisać niestandardowego kodu. Począwszy od wersji 1.2 Swift ma już wszystkie potrzebne metody:

  • coraz długość ciągu: count(string);
  • sprawdzenie, czy ciąg zawiera podciąg: contains(string, substring);
  • sprawdzanie, czy ciąg zaczyna się od podłańcucha: startsWith(string, substring)
  • itd.

Swift 2 to nie to samo.
Suragch

2
Swift 2 : string.hasPrefix („start”)
SwiftArchitect

5

W Swift 3

if((a.range(of: b!, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)) != nil){
    print("Done")
}

4

Proszę bardzo! Gotowy na Xcode 8 i Swift 3.

import UIKit

let mString = "This is a String that contains something to search."
let stringToSearchUpperCase = "String"
let stringToSearchLowerCase = "string"

mString.contains(stringToSearchUpperCase) //true
mString.contains(stringToSearchLowerCase) //false
mString.lowercased().contains(stringToSearchUpperCase) //false
mString.lowercased().contains(stringToSearchLowerCase) //true

3

string.containsString jest dostępny tylko w wersji 10.10 Yosemite (i prawdopodobnie iOS8). Również mostkowanie go do Objective C ulega awarii w 10.9. Próbujesz przekazać NSString do NSCFString. Nie znam różnicy, ale mogę powiedzieć 10.9 barfs, kiedy wykonuje ten kod w aplikacji OS X 10.9.

Oto różnice w Swift z 10.9 i 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/index.html zawiera jest dostępny tylko w 10.10

Zakres String powyżej działa świetnie na 10.9. Uważam, że programowanie na 10.9 jest super stabilne z Xcode beta2. Nie używam placów zabaw za pośrednictwem ani wersji wiersza poleceń z placów zabaw. Zauważyłem, że jeśli zaimportowane są odpowiednie frameworki, autouzupełnianie jest bardzo pomocne.


3

Dzięki nowej składni w swift 4 możesz po prostu

string.contains("Swift 4 is the best")

ciąg jest zmienną ciąg


2

Wersja Xcode 8 / Swift 3:

let string = "hello Swift"

if let range = string.range(of: "Swift") {
    print("exists at range \(range)")
} else {
    print("does not exist")
}

if let lowercaseRange = string.lowercased().range(of: "swift") {
    print("exists at range \(lowercaseRange)")
} else {
    print("does not exist")
}

Możesz także użyć contains:

string.contains("swift") // false
string.contains("Swift") // true

2

Sprawdź, czy zawiera „Witaj”

let s = "Hello World"

if s.rangeOfString("Hello") != nil {
    print("Yes it contains 'Hello'")
}

2

Szybki 4 sposób sprawdzania podciągów, w tym niezbędnego Foundation(lub UIKit) importu ram:

import Foundation // or UIKit

let str = "Oh Canada!"

str.contains("Can") // returns true

str.contains("can") // returns false

str.lowercased().contains("can") // case-insensitive, returns true

O ile nie zaimportowano Foundation(lub UIKit) frameworka, str.contains("Can")spowoduje błąd kompilatora.


Ta odpowiedź przywraca odpowiedź manojldsa , co jest całkowicie poprawne. Nie mam pojęcia, dlaczego tak wiele odpowiedzi przejść przez tyle trudu odtworzyć Foundation„s String.contains(subString: String)metody.


1
// Search string exist in employee name finding.
var empName:NSString! = employeeDetails[filterKeyString] as NSString

Case sensitve search.
let rangeOfSearchString:NSRange! = empName.rangeOfString(searchString, options: NSStringCompareOptions.CaseInsensitiveSearch)

// Not found.
if rangeOfSearchString.location != Foundation.NSNotFound
{
    // search string not found in employee name.
}
// Found
else
{
    // search string found in employee name.
}


0

W iOS 8 i nowszych możesz użyć tych dwóch NSStringmetod:

@availability(iOS, introduced=8.0)
func containsString(aString: String) -> Bool

@availability(iOS, introduced=8.0)
func localizedCaseInsensitiveContainsString(aString: String) -> Bool

Co? wygląda na to, że nie jest dostępne? w wersji dostarczanej z xcode 6.1
Ali

0

Znalazłem kilka interesujących przypadków użycia. Te warianty wykorzystują metodę rangeOfString, a ja dołączam przykład równości, aby pokazać, jak najlepiej wykorzystać funkcje wyszukiwania i porównywania ciągów w Swift 2.0

//In viewDidLoad() I assign the current object description (A Swift String) to self.loadedObjectDescription
self.loadedObjectDescription = self.myObject!.description

Później, po wprowadzeniu zmian do self.myObject, mogę odwoływać się do następujących procedur porównywania ciągów (skonfigurowanych jako leniwe zmienne zwracające Bool). Umożliwia to sprawdzenie stanu w dowolnym momencie.

lazy var objectHasChanges : Bool = {
        guard self.myObject != nil else { return false }
        return !(self.loadedObjectDescription == self.myObject!.description)
    }()

Ten wariant ma miejsce, gdy czasami muszę przeanalizować brakującą właściwość tego obiektu. Wyszukiwanie ciągów pozwala mi znaleźć określone podciągi ustawione na zero (domyślnie przy tworzeniu obiektu).

    lazy var isMissingProperty : Bool = {
        guard self.myObject != nil else { return true }
        let emptyPropertyValue = "myProperty = nil"
        return (self.myObject!.description.rangeOfString(emptyPropertyValue) != nil) ? true : false
    }()

0

Jeśli chcesz sprawdzić, czy jeden ciąg zawiera w sobie inny podciąg, czy nie, możesz to również sprawdzić w ten sposób,

var name = String()  
name = "John has two apples." 

Teraz, jeśli chcesz wiedzieć, czy zawiera nazwę owocu „jabłko”, czy nie, możesz to zrobić,

if name.contains("apple")      
{  
print("Yes , it contains fruit name")    
}    
else      
{    
 print(it does not contain any fruit name)    
}    

Mam nadzieję, że to Ci odpowiada.


-2

Możesz po prostu zrobić to, co wspomniałeś:

import Foundation
...
string.contains("Swift");

Z dokumentów:

StringTyp Swift jest płynnie połączony z NSString klasą Foundation . Jeśli pracujesz z frameworkiem Foundation w Cocoa lub Cocoa Touch, cały NSStringinterfejs API jest dostępny do wywołania dowolnej Stringutworzonej wartości, oprócz funkcji String opisanych w tym rozdziale. Możesz także użyć wartości String w dowolnym interfejsie API, który wymaga instancji NSString.

Trzeba import Foundationzlikwidować te NSStringmetody i udostępnić je do klasy String Swifta.


Nie ja, ale nie, nie ma.
Cezar

tak. Wypróbowałem na placu zabaw, w aplikacji Mac i aplikacji na iOS. Próbowano także w Playground importując kakao, UIKit, Foundation i wszystkie możliwe kombinacje trzech z nich (z wyjątkiem Cocoa / UIKit, co nie ma sensu)
Cezar

Tak już nie jest w przypadku Swift 1.2
Kelvin Lau

-4

SWIFT 4 jest bardzo łatwy !!

if (yourString.contains("anyThing")) {
   Print("Exist")
}

1
Czym różni się to od kilku innych odpowiedzi tutaj?
Ashley Mills,

1
$ swift Welcome to Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1). Type :help for assistance. 1> print ("Ping") Ping 2> Print ("Ping") error: repl.swift:2:1: error: use of unresolved identifier 'Print' Print ("Ping") ^~~~~ Podając niesprawdzoną odpowiedź, która nie działa. Drukuj! = Drukuj.
Fred Gannett
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.