Swift começa com o método?

151

Existe algo como um método beginWith () ou algo semelhante no Swift?

Estou basicamente tentando verificar se uma determinada string começa com outra. Eu também quero que isso não faça distinção entre maiúsculas e minúsculas.

Como você pode perceber, estou apenas tentando fazer um simples recurso de pesquisa, mas parece que estou falhando miseravelmente nisso.

Isto é o que eu gostaria:

digitar "sa" deve me dar resultados para "San Antonio", "Santa Fe", etc. digitar "SA" ou "Sa" ou até "sA" também deve retornar "San Antonio" ou "Santa Fe".

Eu estava usando

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

antes do iOS9 e estava funcionando bem. Após a atualização para o iOS9, no entanto, ele parou de funcionar e agora as pesquisas diferenciam maiúsculas de 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
fonte
Você pode dar um exemplo concreto em que rangeOfString with CaseInsensitiveSearch não funciona conforme o esperado? Eu testei no iOS 9 Simulator e funcionou para mim.
Martin R

Respostas:

362

use em hasPrefixvez de startsWith.

Exemplo:

"hello dolly".hasPrefix("hello")  // This will return true
"hello dolly".hasPrefix("abc")    // This will return false
jobima
fonte
2
OP pede caso insensível e sua resposta é sensível a maiúsculas
Cœur
13
É muito fácil fazer as cordas minúsculas antes da comparação usando"string".lowercased()
TotoroTotoro
12

aqui está uma implementação da extensão Swift de beginWith:

extension String {

  func startsWith(string: String) -> Bool {

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

    return range.startIndex == startIndex
  }

}

Exemplo de uso:

var str = "Hello, playground"

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

Para responder especificamente a distinção entre maiúsculas e minúsculas correspondência de prefixo que não :

em puro Swift (recomendado na maioria das vezes)

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: para um prefixo vazio, ""ambas as implementações retornarãotrue

usando Foundation range(of:options:)

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

nota: para um prefixo vazio, ""ele retornaráfalse

e ser feio com um regex (eu já vi ...)

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 um prefixo vazio, ""ele retornaráfalse

Cœur
fonte
6

No rápido 4 func starts<PossiblePrefix>(with possiblePrefix: PossiblePrefix) -> Bool where PossiblePrefix : Sequence, String.Element == PossiblePrefix.Element será introduzido.

Exemplo de uso:

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

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

Edit: atualizado para o Swift 3.

A classe Swift String possui o método que diferencia maiúsculas de minúsculas hasPrefix(), mas se você deseja uma pesquisa que não diferencia maiúsculas de minúsculas, pode usar o método NSStringrange(of:options:) .

Nota: Por padrão, os métodos NSString não estão disponíveis, mas se vocêimport Foundation estiver.

Assim:

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

As opções podem ser dadas como .caseInsensitiveou [.caseInsensitive]. Você usaria o segundo se quisesse usar opções adicionais, como:

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

Essa abordagem também tem a vantagem de poder usar outras opções com a pesquisa, como .diacriticInsensitivepesquisas. O mesmo resultado não pode ser alcançado simplesmente usando . lowercased()as strings.

Gary Makin
fonte
1

Versão Swift 3:

func startsWith(string: String) -> Bool {
    guard let range = range(of: string, options:[.caseInsensitive]) else {
        return false
    }
    return range.lowerBound == startIndex
}
user2990759
fonte
pode ser mais rápido com .anchored. Veja minha resposta ou a resposta de Oliver Atkinson.
Cœur
1

No Swift 4 com extensões

Minha extensão de exemplo contém 3 funções: Verificação de fazer uma String começar com uma subcadeia, fazer uma String final de uma substring e fazer uma String contém uma subcadeia.

Defina o parâmetro isCaseSensitive como false, se desejar ignorar os caracteres "A" ou "a", caso contrário, defina-o como true.

Veja os comentários no código para obter mais informações sobre como ele 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
            }
        }
    }

Exemplos de como usar:

Para verificar, a String começa com "TEST":

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

Para verificar, a String começa com "test":

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

Para verificar, a String termina com "G123":

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

Para verificar, a String termina com "g123":

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

Para verificar se a String contém "RING12":

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

Para verificar se a String contém "ring12":

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