Swift démarre avec la méthode?

151

Existe-t-il une méthode startsWith () ou quelque chose de similaire dans Swift?

J'essaye essentiellement de vérifier si une certaine chaîne commence par une autre chaîne. Je veux aussi que ce soit insensible à la casse.

Comme vous pourrez peut-être le dire, j'essaie simplement de faire une fonction de recherche simple, mais je semble échouer lamentablement à cela.

Voici ce que j'aimerais:

taper "sa" devrait me donner des résultats pour "San Antonio", "Santa Fe", etc. taper "SA" ou "Sa" ou même "sA" devrait également renvoyer "San Antonio" ou "Santa Fe".

J'utilisais

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

avant iOS9 et cela fonctionnait très bien. Cependant, après la mise à niveau vers iOS9, il a cessé de fonctionner et les recherches sont désormais sensibles à la casse.

    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
la source
Pouvez-vous donner un exemple concret où rangeOfString avec CaseInsensitiveSearch ne fonctionne pas comme prévu? Je l'ai testé dans le simulateur iOS 9 et cela a fonctionné pour moi.
Martin R

Réponses:

362

utiliser à la hasPrefixplace de startsWith.

Exemple:

"hello dolly".hasPrefix("hello")  // This will return true
"hello dolly".hasPrefix("abc")    // This will return false
Jobima
la source
2
OP demande l'insensibilité à la casse et votre réponse est sensible à la casse
Cœur
13
Il est très facile de mettre les chaînes en minuscules avant la comparaison en utilisant"string".lowercased()
TotoroTotoro
12

voici une implémentation d'extension Swift de startsWith:

extension String {

  func startsWith(string: String) -> Bool {

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

    return range.startIndex == startIndex
  }

}

Exemple d'utilisation:

var str = "Hello, playground"

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

Pour répondre spécifiquement à la correspondance de préfixe insensible à la casse :

en pur Swift (recommandé la plupart du temps)

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

ou:

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

note: pour un préfixe vide, les ""deux implémentations renverronttrue

en utilisant Foundation range(of:options:)

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

note: pour un préfixe vide ""il retournerafalse

et être moche avec une regex (je l'ai vu ...)

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

note: pour un préfixe vide, ""il retournerafalse

Cœur
la source
6

Dans Swift 4 func starts<PossiblePrefix>(with possiblePrefix: PossiblePrefix) -> Bool where PossiblePrefix : Sequence, String.Element == PossiblePrefix.Elementsera introduit.

Exemple d'utilisation:

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

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

Edit: mis à jour pour Swift 3.

La classe Swift String a la méthode sensible à la casse hasPrefix(), mais si vous voulez une recherche insensible à la casse, vous pouvez utiliser la méthode NSStringrange(of:options:) .

Remarque: par défaut, les méthodes NSString ne sont pas disponibles, mais si vousimport Foundation .

Alors:

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)");
}

Les options peuvent être données comme .caseInsensitiveou [.caseInsensitive]. Vous utiliseriez la seconde si vous vouliez utiliser des options supplémentaires, telles que:

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

Cette approche a également l'avantage de pouvoir utiliser d'autres options avec la recherche, comme les .diacriticInsensitiverecherches. Le même résultat ne peut pas être obtenu simplement en utilisant . lowercased()sur les chaînes.

Gary Makin
la source
1

Version Swift 3:

func startsWith(string: String) -> Bool {
    guard let range = range(of: string, options:[.caseInsensitive]) else {
        return false
    }
    return range.lowerBound == startIndex
}
user2990759
la source
peut être plus rapide avec .anchored. Voir ma réponse ou la réponse d'Oliver Atkinson.
Cœur
1

Dans Swift 4 avec extensions

Mon exemple d'extension contient 3 fonctions: vérifiez faire un début de chaîne avec une sous-chaîne, faire une fin de chaîne à une sous-chaîne et faire une chaîne contient une sous-chaîne.

Définissez le paramètre isCaseSensitive sur false, si vous souhaitez ignorer les caractères "A" ou "a", sinon définissez-le sur true.

Voir les commentaires dans le code pour plus d'informations sur son fonctionnement.

Code:

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

Exemples d'utilisation:

Pour vérifier, la chaîne commence par "TEST":

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

Pour vérifier, la chaîne commence par "test":

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

Pour vérifier, la chaîne se termine par "G123":

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

Pour vérifier, la chaîne se termine par "g123":

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

Pour vérifier si la chaîne contient "RING12":

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

Pour vérifier si la chaîne contient "ring12":

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