¿Cómo verifico si una cadena contiene otra cadena en Swift?

535

En Objective-Cel código para verificar una subcadena en un NSStringes:

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

Pero, ¿cómo hago esto en Swift?

Rajneesh071
fuente
2
@rckoenes Soy nuevo en Swift, sé cómo lograr este objetivo
C
1
Entonces, ¿por qué no empiezas un parque infantil y lo pruebas?
rckoenes
Si todavía estás cerca, cambia la respuesta aceptada por la del usuario 1021430 ... es correcta
Dan Rosenstark

Respuestas:

1045

Puede hacer exactamente la misma llamada con Swift:

Swift 4 y Swift 5

En Swift 4 String hay una colección de Charactervalores, no era así en Swift 2 y 3, por lo que puede usar este código más conciso 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")
}

Swift mayor

var string = "hello Swift"

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

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

Espero que esta sea una solución útil ya que algunas personas, incluyéndome a mí, encontraron algunos problemas extraños al llamar containsString(). 1

PD. No te olvides deimport Foundation

Notas al pie

  1. Solo recuerde que el uso de funciones de colección en Strings tiene algunos casos extremos que pueden brindarle resultados inesperados, por ejemplo, cuando se trata de emojis u otros grupos de grafemas como letras acentuadas.
Jens Wirth
fuente
13
La documentación de Apple dice: 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 (@"").Entonces, tal vez la comprobación nilno funcione correctamente.
Alex
77
string.lowercaseString.rangeOfString ("swift"). location! = NSNotFound. Lea la documentación ... no recibirá un objeto nulo de vuelta.
TheCodingArt
44
@TheGamingArt Sí, lo harás. Swift realiza viajes de ida y vuelta todo para usted de forma automática, de modo que si el NSRange {NSNotFound, 0}está representado para usted como nulo. Si se trata de un rango real, se representa para usted como un Rango rápido (opcional). Frio.
mate
44
Grr. contieneString no está en los documentos, incluso a partir de Xcode 6.3.1.
Duncan C
19
@TheGoonie: Esto no está llamando NSString's .rangeOfString(). Esto es llamado String's .rangeOfString(), que se declara comofunc rangeOfString(aString: String, options mask: NSStringCompareOptions = default, range searchRange: Range<Index>? = default, locale: NSLocale? = default) -> Range<Index>?
newacct
192

Forma de extensión

Swift 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

En general, Swift 4 tiene un método que contiene , sin embargo, está disponible desde iOS 8.0+


Swift 3.1

Puede escribir extensión contains:y containsIgnoringCaseparaString

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

Versión Swift anterior

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

Ejemplo:

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
Maxim Shoustin
fuente
66
para ignorar el caso, use return self.rangeOfString (find, options: NSStringCompareOptions.CaseInsensitiveSearch)! = nil
masgar
1
Ya no es necesario a menos que no tenga Foundationalrededor ... containsStringfunciona bien.
Dan Rosenstark
55
para swift 3.0. Cambie a continuación: extensión String {func contiene (find: String) -> Bool {return self.range (of: find)! = Nil} func contieneIgnoringCase (find: String) -> Bool {return self.range (of: find , opciones: .caseInsensitive)! = nil}}
Michael Shang el
Para Swift 4 -> extension String {func contiene (find: String) -> Bool {return self.range (of: find)! = Nil} func contieneIgnoringCase (find: String) -> Bool {return self.range (of: find, options: .caseInsensitive)! = nil}}
shokaveli
50

De los documentos, parece que invocar containsString()una cadena debería funcionar:

El tipo de cadena de Swift se conecta sin problemas a la clase NSString de Foundation. Si está trabajando con el framework Foundation en Cocoa o Cocoa Touch, toda la API de NSString está disponible para invocar cualquier valor de String que cree, además de las características de String descritas en este capítulo. También puede usar un valor de cadena con cualquier API que requiera una instancia de NSString.

Sin embargo, no parece funcionar de esa manera.

Si intenta utilizar someString.containsString(anotherString), obtendrá un error de tiempo de compilación que indica 'String' does not contain a member named 'containsString'.

Por lo tanto, le quedan algunas opciones, una de las cuales es unir explícitamente su Stringobjetivo con Objective-C mediante el uso de bridgeToObjectiveC()otros dos que implican explícitamente el uso de NSStringy el último implica lanzar el Stringa unNSString

Al hacer un puente, obtendría:

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

Al escribir explícitamente la cadena como un NSString, obtendría:

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

Si tiene un existente String, puede inicializar un NSString a partir de él utilizando NSString (string :):

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

Y, por último, puede emitir un existente Stringa un de la NSStringsiguiente manera

var string = "hello Swift"
if (string as NSString).containsString("Swift") {
    println("YES")
}
Cezar
fuente
44
El último ejemplo (no he probado otros) se bloquea en iOS 7 (dispositivo); Las aplicaciones rápidas deberían funcionar bien en iOS 7. El error que obtengo es [__NSCFString containsString:]: unrecognized selector sent to instance. Además, no puedo encontrar el método containsStringen los documentos de desarrollo para confirmar si es nuevo para iOS 8.
Jason Leach
Interesante. Solo probé esto en un patio de recreo. Lo intentaré más tarde cuando esté en mi computadora.
Cezar
Las opciones tercera y cuarta son las únicas que el compilador permitió. tanto dormir por mí en la beta 4 en iOS 7.
palmi
38

Otro. Admite mayúsculas y opciones diacríticas.

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

Uso

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

iOS 9+

Función insensible a mayúsculas y diacríticas disponible desde iOS 9.

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

A partir de Xcode 7.1 y Swift 2.1 containsString()está funcionando bien para mí.

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

Swift 4:

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

Y un ejemplo de Swift 4 que no distingue entre mayúsculas y minúsculas:

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

O usando una Stringextensión que no distingue entre mayúsculas y minúsculas :

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
Murray Sagal
fuente
3
es necesario import Foundation, de lo contrario esto no funcionará.
Andrii Chernenko
Cualquiera import UIKitde los dos import Foundationes obligatorio, al menos con iOS 11 y Swift 4.
Murray Sagal
Pero eso es sensible a mayúsculas y minúsculas. ¿Cómo se hace la comparación mientras se ignora el caso? ¿Como en Java String.equalsIgnoreCase (anotherString)?
zulkarnain shah
@zulkarnainshah Agregué un ejemplo a la respuesta.
Murray Sagal el
@MurraySagal Eso todavía no es una búsqueda insensible a mayúsculas y minúsculas Está convirtiendo la cadena original en minúsculas y luego la compara explícitamente con una cadena en minúsculas. Hará el trabajo, pero esa no es la forma ideal de hacerlo
zulkarnain shah
22

En Swift 4.2

Utilizar

func contains(_ str: String) -> Bool

Ejemplo

let string = "hello Swift"
let containsSwift = string.contains("Swift")
print(containsSwift) // prints true
Saranjith
fuente
44
Tenga en cuenta que esto requiere que importe Foundation.
rmaddy
16

> EN SWIFT 3.0

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

Salida

String Contains Another String
Ashok R
fuente
15

Puedes hacer esto muy fácilmente en Swift usando el código:

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

Solo una adición a las respuestas aquí.

También puede hacer una prueba local sin distinción entre mayúsculas y minúsculas utilizando:

 - (BOOL)localizedCaseInsensitiveContainsString:(NSString *)aString

Ejemplo:

    import Foundation

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

ACTUALIZAR

Esto es parte de Foundation Framework para iOS y Mac OS X 10.10.x y era parte de 10.10 en el momento de mi publicación original.

Documento generado: 2014-06-05 12:26:27 -0700 Notas de la versión de OS X Copyright © 2014 Apple Inc. Todos los derechos reservados.

Notas de la versión de OS X 10.10 Cocoa Foundation Framework

NSString ahora tiene los siguientes dos métodos convenientes:

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

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

Markhunte
fuente
1
Tenga en cuenta que este enfoque requiere iOS 8.
Andrew Ebling
9

Aquí está mi primera puñalada en el patio de juegos rápido. Extiendo String proporcionando dos nuevas funciones (contiene y contieneIgnoreCase)

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

Úselo así

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

Agradecería cualquier comentario :)

Conocer
fuente
Siguiente paso: Haga de esta una función genérica que funcione en todas las colecciones :-) Por ejemplo, verifique la función incorporada beginWith (). En la variante 'ignorar caso', solo minúsculas las cadenas una vez (let lc = other.lowercaseString antes de hacer)
hnh
9

De todas las respuestas aquí, creo que o bien no funcionan, o son un poco hack (regresando a NSString). Es muy probable que la respuesta correcta a esto haya cambiado con las diferentes versiones beta.

Esto es lo que uso:

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

El "! = Nil" se requirió con Beta 5.

usuario1021430
fuente
6

Aquí estás:

let s = "hello Swift"
if let textRange = s.rangeOfString("Swift") {
    NSLog("exists")
}
Stéphane de Luca
fuente
En algún momento puede necesitar una forma compacta de la siguiente manera: let rangeIfExists = string.rangeOfString ("Swift") ?? falso que devuelve falso como un booleano si no está contenido o el NSRange de lo contrario
Stéphane de Luca
5

No necesita escribir ningún código personalizado para esto. A partir de la versión 1.2, Swift ya ha tenido todos los métodos que necesita:

  • consiguiendo longitud de la cadena: count(string);
  • comprobar si la cadena contiene subcadena: contains(string, substring);
  • Comprobando si la cadena comienza con la subcadena: startsWith(string, substring)
  • y etc.
Max Ivashkevich
fuente
Swift 2 no es lo mismo.
Suragch
2
Swift 2 : string.hasPrefix ("inicio")
SwiftArchitect
5

En Swift 3

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

¡Aqui tienes! Listo para Xcode 8 y 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
Carlitos
fuente
3

string.containsString solo está disponible en 10.10 Yosemite (y probablemente iOS8). También lo conecta a ObjectiveC se bloquea en 10.9. Estás intentando pasar un NSString a NSCFString. No sé la diferencia, pero puedo decir 10.9 barfs cuando ejecuta este código en una aplicación OS X 10.9.

Estas son las diferencias en Swift con 10.9 y 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/index.html contieneString solo está disponible en 10.10

Range of String anterior funciona muy bien en 10.9. Estoy descubriendo que el desarrollo en 10.9 es súper estable con Xcode beta2. No uso los parques infantiles ni la versión de línea de comandos de los parques infantiles. Estoy descubriendo que si se importan los marcos adecuados, el autocompletado es muy útil.

Buen tiempo
fuente
3

Con y una nueva sintaxis en swift 4 puedes simplemente

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

cadena es su variable de cadena

100tomer
fuente
2

Versión 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")
}

También puedes usar contains:

string.contains("swift") // false
string.contains("Swift") // true
JAL
fuente
2

Comprueba si contiene 'Hola'

let s = "Hello World"

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

fuente
2

4 formas rápidas de verificar las subcadenas, incluida la importación de marco necesaria Foundation(o 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

A menos que se importe Foundation(o UIKit) el marco, str.contains("Can")dará un error del compilador.


Esta respuesta es regurgitar la respuesta de manojlds , que es completamente correcta. No tengo idea de por qué tantas respuestas pasan por tantos problemas para recrear Foundationel String.contains(subString: String)método.

NonCreature0714
fuente
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.
}
abhi
fuente
0

En iOS 8 y versiones posteriores, puede usar estos dos NSStringmétodos:

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

@availability(iOS, introduced=8.0)
func localizedCaseInsensitiveContainsString(aString: String) -> Bool
Rudolf Adamkovič
fuente
¿Qué? parece que no está disponible? en la versión que viene con xcode 6.1
Ali
0

He encontrado un par de casos de uso interesantes. Estas variantes hacen uso del método rangeOfString e incluyo el ejemplo de igualdad para mostrar cómo uno puede usar mejor las funciones de búsqueda y comparación de Strings en Swift 2.0

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

Más tarde, después de realizar cambios en self.myObject, puedo referirme a las siguientes rutinas de comparación de cadenas (configuradas como variables perezosas que devuelven un Bool). Esto permite verificar el estado en cualquier momento.

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

Una variante de esto ocurre cuando a veces necesito analizar una propiedad que falta en ese objeto. Una búsqueda de cadena me permite encontrar una subcadena particular que se establece en cero (el valor predeterminado cuando se crea un objeto).

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

Si desea verificar que una Cadena contenga otra Subcadena dentro o no, también puede verificarla así,

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

Ahora, en esta cadena en particular, si desea saber si contiene el nombre de fruta 'manzana' o no, puede hacerlo,

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

Espero que esto funcione para usted.

Varsha Shivhare
fuente
-2

Puedes hacer lo que has mencionado:

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

De los documentos:

El Stringtipo de Swift se conecta a la perfección con la NSString clase de Foundation . Si está trabajando con el framework Foundation en Cocoa o Cocoa Touch, toda la NSStringAPI está disponible para solicitar cualquier Stringvalor que cree, además de las características de String descritas en este capítulo. También puede usar un valor de cadena con cualquier API que requiera una instancia de NSString.

Debe import Foundationunir los NSStringmétodos y ponerlos a disposición de la clase String de Swift.

manojlds
fuente
Yo no, pero no, no lo hace.
Cezar
Sí. Probado en un patio de juegos, en una aplicación de Mac y en una aplicación de iOS. También probé en Playground importando Cocoa, UIKit, Foundation y todas las combinaciones posibles de los tres (excepto Cocoa / UIKit, que no tiene sentido)
Cezar
Este ya no es el caso a partir de Swift 1.2
Kelvin Lau
-4

¡SWIFT 4 es muy fácil!

if (yourString.contains("anyThing")) {
   Print("Exist")
}
Oscar Castellon
fuente
1
¿Cómo es esto diferente a varias de las otras respuestas aquí?
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") ^~~~~ Al proporcionar una respuesta no probada que no funciona. Imprimir! = Imprimir.
Fred Gannett