Swift comienza con el método?

151

¿Existe tal cosa como un método beginWith () o algo similar en Swift?

Básicamente estoy tratando de verificar si cierta cadena comienza con otra cadena. También quiero que no distinga entre mayúsculas y minúsculas.

Como puede notar, solo estoy tratando de hacer una función de búsqueda simple, pero parece que estoy fallando miserablemente en esto.

Esto es lo que me gustaría:

escribir "sa" debería darme resultados para "San Antonio", "Santa Fe", etc. escribir "SA" o "Sa" o incluso "sA" también debería devolver "San Antonio" o "Santa Fe".

Yo estaba usando

self.rangeOfString(find, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil 

antes de iOS9 y funcionaba bien. Sin embargo, después de actualizar a iOS9, dejó de funcionar y ahora las búsquedas distinguen entre mayúsculas y minúsculas.

    var city = "San Antonio"
    var searchString = "san "
    if(city.rangeOfString(searchString, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil){
        print("San Antonio starts with san ");
    }

    var myString = "Just a string with san within it"

    if(myString.rangeOfString(searchString, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil){
        print("I don't want this string to print bc myString does not start with san ");
    }
Arthur Garza
fuente
¿Puede dar un ejemplo concreto donde rangeOfString con CaseInsensitiveSearch no funciona como se esperaba? Lo probé en el simulador de iOS 9 y funcionó para mí.
Martin R

Respuestas:

362

usar en hasPrefixlugar de startsWith.

Ejemplo:

"hello dolly".hasPrefix("hello")  // This will return true
"hello dolly".hasPrefix("abc")    // This will return false
Jobima
fuente
2
OP pide mayúsculas y minúsculas y su respuesta es sensible a mayúsculas y minúsculas
Cœur
13
Es muy fácil poner las cadenas en minúsculas antes de la comparación usando"string".lowercased()
TotoroTotoro
12

Aquí hay una implementación de extensión Swift de comienza con:

extension String {

  func startsWith(string: String) -> Bool {

    guard let range = rangeOfString(string, options:[.AnchoredSearch, .CaseInsensitiveSearch]) else {
      return false
    }

    return range.startIndex == startIndex
  }

}

Ejemplo de uso:

var str = "Hello, playground"

let matches    = str.startsWith("hello") //true
let no_matches = str.startsWith("playground") //false
Oliver Atkinson
fuente
10

Para responder específicamente la coincidencia de prefijos sin distinción entre mayúsculas y minúsculas :

en Swift puro (recomendado la mayor parte del tiempo)

extension String {
    func caseInsensitiveHasPrefix(_ prefix: String) -> Bool {
        return lowercased().hasPrefix(prefix.lowercased())
    }
}

o:

extension String {
    func caseInsensitiveHasPrefix(_ prefix: String) -> Bool {
        return lowercased().starts(with: prefix.lowercased())
    }
}

nota: para un prefijo vacío, ""ambas implementaciones devolverántrue

usando Foundation range(of:options:)

extension String {
    func caseInsensitiveHasPrefix(_ prefix: String) -> Bool {
        return range(of: prefix, options: [.anchored, .caseInsensitive]) != nil
    }
}

nota: para un prefijo vacío ""devolveráfalse

y ser feo con una expresión regular (lo he visto ...)

extension String {
    func caseInsensitiveHasPrefix(_ prefix: String) -> Bool {
        guard let expression = try? NSRegularExpression(pattern: "\(prefix)", options: [.caseInsensitive, .ignoreMetacharacters]) else {
            return false
        }
        return expression.firstMatch(in: self, options: .anchored, range: NSRange(location: 0, length: characters.count)) != nil
    }
}

nota: para un prefijo vacío ""devolveráfalse

Coeur
fuente
6

En Swift 4 func starts<PossiblePrefix>(with possiblePrefix: PossiblePrefix) -> Bool where PossiblePrefix : Sequence, String.Element == PossiblePrefix.Element se presentará.

Ejemplo de uso:

let a = 1...3
let b = 1...10

print(b.starts(with: a))
// Prints "true"
Bueno
fuente
6

Editar: actualizado para Swift 3.

La clase Swift String tiene un método hasPrefix()que distingue entre mayúsculas y minúsculas, pero si desea una búsqueda que no distinga entre mayúsculas y minúsculas, puede usar el método NSString range(of:options:).

Nota: Por defecto, los métodos NSString no están disponibles, pero si import Foundationlo están.

Entonces:

import Foundation
var city = "San Antonio"
var searchString = "san "
let range = city.range(of: searchString, options:.caseInsensitive)
if let range = range {
    print("San Antonio starts with san at \(range.startIndex)");
}

Las opciones se pueden dar como .caseInsensitiveo [.caseInsensitive]. Usaría el segundo si quisiera usar opciones adicionales, como:

let range = city.range(of: searchString, options:[.caseInsensitive, .backwards])

Este enfoque también tiene la ventaja de poder utilizar otras opciones con la búsqueda, como las .diacriticInsensitivebúsquedas. El mismo resultado no se puede lograr simplemente usando . lowercased()las cadenas.

Gary Makin
fuente
1

Versión Swift 3:

func startsWith(string: String) -> Bool {
    guard let range = range(of: string, options:[.caseInsensitive]) else {
        return false
    }
    return range.lowerBound == startIndex
}
usuario2990759
fuente
puede ser más rápido con .anchored. Vea mi respuesta o la respuesta de Oliver Atkinson.
Cœur
1

En Swift 4 con extensiones

Mi extensión-ejemplo contiene 3 funciones: marcar hacer un String que comience con una subString, hacer un String end a un subString y hacer un String que contenga un subString.

Establezca el parámetro isCaseSensitive en false, si desea ignorar los caracteres "A" o "a", de lo contrario, configúrelo en true.

Vea los comentarios en el código para obtener más información sobre cómo funciona.

Código:

    import Foundation

    extension String {
        // Returns true if the String starts with a substring matching to the prefix-parameter.
        // If isCaseSensitive-parameter is true, the function returns false,
        // if you search "sA" from "San Antonio", but if the isCaseSensitive-parameter is false,
        // the function returns true, if you search "sA" from "San Antonio"

        func hasPrefixCheck(prefix: String, isCaseSensitive: Bool) -> Bool {

            if isCaseSensitive == true {
                return self.hasPrefix(prefix)
            } else {
                var thePrefix: String = prefix, theString: String = self

                while thePrefix.count != 0 {
                    if theString.count == 0 { return false }
                    if theString.lowercased().first != thePrefix.lowercased().first { return false }
                    theString = String(theString.dropFirst())
                    thePrefix = String(thePrefix.dropFirst())
                }; return true
            }
        }
        // Returns true if the String ends with a substring matching to the prefix-parameter.
        // If isCaseSensitive-parameter is true, the function returns false,
        // if you search "Nio" from "San Antonio", but if the isCaseSensitive-parameter is false,
        // the function returns true, if you search "Nio" from "San Antonio"
        func hasSuffixCheck(suffix: String, isCaseSensitive: Bool) -> Bool {

            if isCaseSensitive == true {
                return self.hasSuffix(suffix)
            } else {
                var theSuffix: String = suffix, theString: String = self

                while theSuffix.count != 0 {
                    if theString.count == 0 { return false }
                    if theString.lowercased().last != theSuffix.lowercased().last { return false }
                    theString = String(theString.dropLast())
                    theSuffix = String(theSuffix.dropLast())
                }; return true
            }
        }
        // Returns true if the String contains a substring matching to the prefix-parameter.
        // If isCaseSensitive-parameter is true, the function returns false,
        // if you search "aN" from "San Antonio", but if the isCaseSensitive-parameter is false,
        // the function returns true, if you search "aN" from "San Antonio"
        func containsSubString(theSubString: String, isCaseSensitive: Bool) -> Bool {

            if isCaseSensitive == true {
                return self.range(of: theSubString) != nil
            } else {
                return self.range(of: theSubString, options: .caseInsensitive) != nil
            }
        }
    }

Ejemplos de uso:

Para verificar, la cadena comienza con "TEST":

    "testString123".hasPrefixCheck(prefix: "TEST", isCaseSensitive: true) // Returns false
    "testString123".hasPrefixCheck(prefix: "TEST", isCaseSensitive: false) // Returns true

Para verificar, la Cadena comienza con "prueba":

    "testString123".hasPrefixCheck(prefix: "test", isCaseSensitive: true) // Returns true
    "testString123".hasPrefixCheck(prefix: "test", isCaseSensitive: false) // Returns true

Para comprobar, finalice la cadena con "G123":

    "testString123".hasSuffixCheck(suffix: "G123", isCaseSensitive: true) // Returns false
    "testString123".hasSuffixCheck(suffix: "G123", isCaseSensitive: false) // Returns true

Para comprobar, finalice la cadena con "g123":

    "testString123".hasSuffixCheck(suffix: "g123", isCaseSensitive: true) // Returns true
    "testString123".hasSuffixCheck(suffix: "g123", isCaseSensitive: false) // Returns true

Para verificar, la cadena contiene "RING12":

    "testString123".containsSubString(theSubString: "RING12", isCaseSensitive: true) // Returns false
    "testString123".containsSubString(theSubString: "RING12", isCaseSensitive: false) // Returns true

Para verificar, la cadena contiene "ring12":

    "testString123".containsSubString(theSubString: "ring12", isCaseSensitive: true) // Returns true
    "testString123".containsSubString(theSubString: "ring12", isCaseSensitive: false) // Returns true
CaOs433
fuente