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.