Як перевірити, чи рядок містить інший рядок у Swift?


535

У Objective-Cкоді, щоб перевірити наявність підрядка в an, NSStringє:

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

Але як це зробити у Свіфті?


2
@rckoenes Я новачок в стриж, я знаю , як зробити це ObjectiveC
Rajneesh071

1
Тоді чому б ви просто не запустити ігровий майданчик і спробувати його.
rckoenes

Якщо ви все ще знаходитесь навколо, будь ласка, змініть прийняту відповідь на відповідь користувачем1021430 ... це правильно
Dan Rosenstark

Відповіді:


1044

З Swift ви можете зробити такий самий дзвінок:

Swift 4 та Swift 5

У Swift 4 String - це набір Characterзначень, це не було так у Swift 2 та 3, тому ви можете використовувати цей більш стислий код 1 :

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

Швидкий 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")
}

Старіший Свіфт

var string = "hello Swift"

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

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

Я сподіваюся, що це корисне рішення, оскільки деякі люди, включаючи мене, стикалися з якимись дивними проблемами при дзвінках containsString(). 1

PS. Не забувайтеimport Foundation

Виноски

  1. Пам'ятайте лише, що використання функцій колекції на Strings має деякі крайні випадки, які можуть давати неочікувані результати, наприклад, коли ви маєте справу з емоджи або іншими кластерами графем, як букви з наголосом.

13
Документація Apple говорить: 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 (@"").Тому, можливо, просто перевірка на те, nilчи не буде працювати належним чином.
Олексій

7
string.lowercaseString.rangeOfString ("стрімкий"). location! = NSNotFound. Будь ласка, прочитайте документацію .. ви не отримаєте нульовий об’єкт назад.
TheCodingArt

4
@TheGamingArt Так. Швидко об’їжджайте все для вас автоматично, так що якщо NSRange є, {NSNotFound, 0}він буде представлений для вас як нуль. Якщо це фактичний діапазон, він представляється для вас як діапазон Swift (необов’язково). Класно.
мат

4
Grr міститьString не в документах, навіть у Xcode 6.3.1.
Дункан C

19
@TheGoonie: Це не називає NSString«S .rangeOfString(). Це заклик String's .rangeOfString(), який оголошено якfunc rangeOfString(aString: String, options mask: NSStringCompareOptions = default, range searchRange: Range<Index>? = default, locale: NSLocale? = default) -> Range<Index>?
newacct

192

Спосіб розширення

Швидкий 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

Як правило, Swift 4 містить метод, проте він доступний в iOS 8.0+


Швидкий 3.1

Ви можете написати розширення contains:і containsIgnoringCaseдляString

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

Старіша версія 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
     }
}

Приклад:

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
ігнорувати випадки використання return self.rangeOfString (знайти, параметри: NSStringCompareOptions.CaseInsensitiveSearch)! = nil
masgar

1
Більше не потрібно, якщо у вас немає Foundationнавколо ... containsStringпрацює чудово.
Дан Розенстарк

5
для швидкого 3.0. Змініть на нижче: рядок розширення {func містить (знайдіть: String) -> Bool {поверніть self.range (з: find)! = Nil} func containsIgnoringCase (find: String) -> Bool {return self.range (of: find , параметри: .caseInsensitive)! = nil}}
Майкл Шан

Для Swift 4 -> String розширення {func містить (знайти: String) -> Bool {повернення self.range (of: find)! = Nil} func containsIgnoringCase (find: String) -> Bool {return self.range (of: знайти, параметри: .caseInsensitive)! = nil}}
shokaveli

50

З документів виходить, що виклик containsString()на String повинен працювати:

Тип рядка Swift безперешкодно з'єднаний з класом NSString Foundation. Якщо ви працюєте з основою Foundation в Cocoa або Cocoa Touch, весь API NSString доступний для виклику будь-якого створеного вами String, крім функцій String, описаних у цій главі. Ви також можете використовувати значення String з будь-яким API, для якого потрібен екземпляр NSString.

Однак, схоже, це не працює так.

Якщо ви спробуєте використовувати someString.containsString(anotherString), ви отримаєте помилку часу компіляції, яка констатує 'String' does not contain a member named 'containsString'.

Таким чином, ви залишилися кілька варіантів, один з яких явно з'єднати СВІЙ Stringдо Objective-C за допомогою bridgeToObjectiveC()двох інших втягують в явному вигляді при допомоги пристроїв NSStringі кінцевий один включає виливок StringАньNSString

Об’єднавши, ви отримаєте:

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

Ввівши явно рядок у вигляді NSString, ви отримаєте:

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

Якщо у вас є існуючий String, ви можете ініціалізувати з нього NSString, використовуючи NSString (рядок :):

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

І, нарешті, ви можете привласнити існуюче Stringдо а, NSStringяк показано нижче

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

4
Останній приклад (я не пробував інших) збоїв для мене на iOS 7 (пристрій); Швидкі програми повинні працювати добре на iOS 7. Помилка [__NSCFString containsString:]: unrecognized selector sent to instance. Крім того, я не можу знайти метод containsStringу програмах розробників, щоб підтвердити, чи є його новим для iOS 8.
Джейсон Ліч

Цікаво. Я тестував це лише на дитячому майданчику. Я спробую пізніше, коли я буду за комп'ютером.
Цезар

третій та четвертий варіанти - єдині, дозволені компілятором. обидва аварії для мене в бета-версії 4 в iOS 7.
palmi

38

Інший. Підтримує регістри випадку та діакритики.

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

Використання

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

iOS 9+

Корпус та діакритична нечутлива функція доступна з iOS 9.

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

31

Станом на Xcode 7.1 і Swift 2.1 containsString()для мене добре працює.

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

Швидкий 4:

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

І приклад Swift 4, нечутливий до випадку:

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

Або використовуючи Stringрозширення з урахуванням регістру :

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
вам потрібно import Foundation, інакше це не спрацює.
Андрій Черненко

Будь-який import UIKitз import Foundationних потрібен, принаймні з iOS 11 та Swift 4.
Мюррей Сагал

Але це враховує регістри. Як ви робите порівняння, ігноруючи випадок. Як у java String.equalsIgnoreCase (anotherString)?
zulkarnain shah

@zulkarnainshah Я додав приклад до відповіді.
Мюррей Сагал

@MurraySagal Thats все ще не стосується нечутливого пошуку. Ви перетворюєте початкову рядок у малі регістри, а потім явно порівнюєте її з нижньою літерами. Це зробить роботу, але це не ідеальний спосіб зробити це
zulkarnain shah

22

У Swift 4.2

Використовуйте

func contains(_ str: String) -> Bool

Приклад

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

4
Зауважте, що для цього потрібно імпортувати Foundation.
rmaddy

16

> В SWIFT 3.0

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

Вихідні дані

String Contains Another String

15

Це можна зробити дуже просто в Swift, використовуючи код:

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

10

Просто додаток до відповідей тут.

Ви також можете зробити тест на нечутливість місцевого випадку, використовуючи:

 - (BOOL)localizedCaseInsensitiveContainsString:(NSString *)aString

Приклад:

    import Foundation

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

ОНОВЛЕННЯ

Це частина основи Foundation для iOS та Mac OS X 10.10.x і входила в 10.10 під час моєї оригінальної публікації.

Документ створено: 05.06.2014 12:26:27 -0700 Примітки до випуску ОС X Copyright © 2014 Apple Inc. Усі права захищені.

ОС X 10.10 Примітки до випуску Рамки фундаменту какао

Тепер NSString має два методи зручності:

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

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


1
Будьте в курсі, що цей підхід вимагає iOS 8.
Ендрю Еблінг

9

Ось мій перший удар у цьому на швидкому майданчику. Я розширюю String, надаючи дві нові функції (містить і міститьIgnoreCase)

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

Використовуйте його так

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

Я вітаю будь-які відгуки :)


Наступний крок: зробіть цю загальну функцію, яка працює на всіх колекціях :-) Наприклад, оформляйте вбудовану функцію startWith (). У варіанті "ігнорувати випадок" лише рядки рядків один раз (нехай lc = other.lowercaseString перед цим)
hnh

9

З усіх відповідей тут, я думаю, що вони або не працюють, або вони трохи зламають (відкидання назад до NSString). Цілком імовірно, що правильна відповідь на це змінилася в різних бета-версіях.

Ось що я використовую:

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

"! = Нуль" став необхідним для Beta 5.


6

Ось ви:

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

Колись вам може знадобитися компактна форма таким чином: нехай rangeIfExists = string.rangeOfString ("Swift") ?? false, що або повертає false як булеве, якщо воно не міститься, або NSRange в іншому випадку
Stéphane de Luca

5

Для цього вам не потрібно писати спеціальний код. Починаючи з версії 1.2, Swift вже застосував усі необхідні методи:

  • Довжина рядка: count(string);
  • перевірки , якщо рядок містить підрядок: contains(string, substring);
  • перевірка, чи починається рядок із підрядка: startsWith(string, substring)
  • і т.д.

Swift 2 - не те саме.
Сурагч

2
Swift 2 : string.hasPrefix ("старт")
SwiftArchitect


4

Ось ви йдете! Готовий до Xcode 8 та 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 доступний лише у 10.10 Yosemite (і, мабуть, iOS8). Крім того, з'єднання його з об'єктивомCC9 підривається в 10.9. Ви намагаєтесь передати NSString до NSCFString. Я не знаю різниці, але я можу сказати 10,9 барф, коли він виконує цей код у додатку OS X 10.9.

Ось відмінності у Swift з 10.9 та 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/index.html containsString доступний лише у 10.10

Діапазон рядків вище працює чудово на 10,9. Я знаходжу, що розробляється на 10,9 є супер стабільним з Xcode beta2. Я не використовую ігрові майданчики через або командний рядок ігрових майданчиків. Я знаходжу, чи імпортовані належні рамки, автозаповнення дуже корисно.


3

З і новим синтаксисом у swift 4 ви просто можете

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

string - це ваша змінна строка


2

Версія 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")
}

Ви також можете використовувати contains:

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

2

Перевірте, чи містить він "Привіт"

let s = "Hello World"

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

2

Швидкий 4 спосіб перевірити наявність підрядів, включаючи необхідний Foundation(або UIKit) імпорт фреймворку:

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

Якщо Foundation(чи UIKit) рамка не імпортується, це str.contains("Can")призведе до помилки компілятора.


Ця відповідь регулює відповідь Манольдса , що є абсолютно правильним. Я поняття не маю , чому так багато відповідей пройти через стільки клопоту , щоб відтворити Foundation«s String.contains(subString: String)метод.


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

В iOS 8 та новіших версіях ви можете використовувати ці два NSStringметоди:

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

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

Що? схоже, його немає? у версії, що постачається з xcode 6.1
Алі

0

Я знайшов пару цікавих випадків використання. Ці варіанти використовують метод rangeOfString, і я включаю приклад рівності, щоб показати, як можна найкраще використовувати функції пошуку та порівняння Strings у Swift 2.0

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

Пізніше, коли я змінив self.myObject, я можу посилатися на наступні процедури порівняння рядків (налаштування як ледачі змінні, які повертають Bool). Це дозволяє перевірити стан у будь-який час.

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

Варіант цього трапляється, коли іноді мені потрібно проаналізувати відсутність властивості на цьому об'єкті. Пошук рядків дозволяє мені знайти певну підрядку, встановлену на нуль (за замовчуванням, коли створюється об’єкт).

    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

Якщо ви хочете перевірити, чи одна рядок містить іншу підрядку, чи ні, ви також можете перевірити її,

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

Тепер, якщо ви хочете дізнатися, чи містить вона назва фрукта "яблуко" чи ні, ви можете зробити це,

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

Сподіваюся, це працює для вас.


-2

Ви можете просто робити те, що ви згадали:

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

З документів:

StringТип Свіфта мостово пов'язаний з NSString класом Foundation . Якщо ви працюєте з основою Foundation в Cocoa або Cocoa Touch, весь NSStringAPI доступний для дзвінків на будь-який String створеного вами значення, крім функцій String, описаних у цій главі. Ви також можете використовувати значення String з будь-яким API, для якого потрібен екземпляр NSString.

Вам потрібно import Foundationпереадресувати NSStringметоди та зробити їх доступними для класу Swift's String.


Не я, але ні, це не так.
Цезар

так. Пробували на ігровій площадці, в додатку для Mac та в додатку для iOS. Також спробували на дитячому майданчику, що імпортує какао, UIKit, Foundation та всі можливі комбінації цих трьох (крім какао / UIKit, що не має сенсу)
Cezar

Це вже не так, як у Swift 1.2
Келвін Лау

-4

SWIFT 4 дуже простий !!

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

1
Чим це відрізняється від кількох інших відповідей тут?
Ешлі Міллз

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") ^~~~~ Надавши неперевірену відповідь, яка не працює. Друк! = Друк.
Фред Ганнетт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.