Свифт начинается с метода?

151

Есть ли такая вещь, как метод StartWith () или что-то подобное в Swift?

Я в основном пытаюсь проверить, начинается ли определенная строка с другой строки. Я также хочу, чтобы он не учитывал регистр.

Как вы могли бы сказать, я просто пытаюсь сделать простую функцию поиска, но мне кажется, что мне это не удается.

Это то, что я хотел бы:

ввод "sa" должен дать мне результаты для "Сан-Антонио", "Санта-Фе" и т. д. ввод "SA", "Sa" или даже "sA" также должен возвращать "Сан-Антонио" или "Санта-Фе".

Я использовал

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

до iOS9 и все работало просто отлично. Однако после обновления до iOS9 он перестал работать, и теперь поиск выполняется с учетом регистра.

    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 ");
    }
Артур Гарза
источник
Можете ли вы привести конкретный пример, где rangeOfString с CaseInsensitiveSearch не работает должным образом? Я протестировал его в iOS 9 Simulator, и он работал на меня.
Мартин Р

Ответы:

362

использовать hasPrefixвместо startsWith.

Пример:

"hello dolly".hasPrefix("hello")  // This will return true
"hello dolly".hasPrefix("abc")    // This will return false
jobima
источник
2
ОП просит, чтобы регистр не учитывался, а ваш ответ чувствителен к регистру
Cœur
13
Перед сравнением очень легко сделать строчные буквы строчными"string".lowercased()
TotoroTotoro
12

Вот реализация Swift для расширения opensWith:

extension String {

  func startsWith(string: String) -> Bool {

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

    return range.startIndex == startIndex
  }

}

Пример использования:

var str = "Hello, playground"

let matches    = str.startsWith("hello") //true
let no_matches = str.startsWith("playground") //false
Оливер Аткинсон
источник
10

Чтобы ответить конкретно на регистр без учета соответствия префиксов:

в чистом Swift (рекомендуется большую часть времени)

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

или:

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

примечание: для пустого префикса ""обе реализации вернутсяtrue

используя Фонд range(of:options:)

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

примечание: для пустого префикса ""он вернетсяfalse

и быть некрасивым с регулярным выражением (я видел это ...)

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

примечание: для пустого префикса ""он вернетсяfalse

Кер
источник
6

В Swift 4 func starts<PossiblePrefix>(with possiblePrefix: PossiblePrefix) -> Bool where PossiblePrefix : Sequence, String.Element == PossiblePrefix.Elementбудут введены.

Пример использования:

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

print(b.starts(with: a))
// Prints "true"
Буэно
источник
6

Редактировать: обновлено для Swift 3.

Класс Swift String имеет метод с учетом регистра hasPrefix(), но если вам нужен поиск без учета регистра, вы можете использовать метод NSString range(of:options:).

Примечание: По умолчанию, методы NSString являются не доступны, но если вы import Foundationих.

Так:

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

Опции могут быть заданы как .caseInsensitiveили [.caseInsensitive]. Вы бы использовали второй, если вы хотите использовать дополнительные параметры, такие как:

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

Этот подход также имеет преимущество, заключающееся в возможности использовать другие параметры поиска, такие как .diacriticInsensitiveпоиск. Тот же результат не может быть достигнут просто с помощью . lowercased()строк.

Гэри Макин
источник
1

Версия Swift 3:

func startsWith(string: String) -> Bool {
    guard let range = range(of: string, options:[.caseInsensitive]) else {
        return false
    }
    return range.lowerBound == startIndex
}
user2990759
источник
может быть быстрее с .anchored. Смотрите мой ответ или ответ Оливера Аткинсона.
Cœur
1

В Swift 4 с расширениями

Мое разгибание пример содержит 3 функции: проверку сделать строки начать с подстрокой, сделать строковый конец к подстроке и сделать Строку содержит подстроку.

Установите для параметра isCaseSensitive значение false, если вы хотите игнорировать символы «A» или «a», в противном случае установите для него значение true.

Смотрите комментарии в коде для получения дополнительной информации о том, как это работает.

Код:

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

Примеры как использовать:

Для проверки начинайте String с «TEST»:

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

Для проверки String начинаем с «test»:

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

Для проверки конец строки следует на «G123»:

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

Для проверки конец строки следует на «g123»:

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

Для проверки строка содержит «RING12»:

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

Для проверки в строке есть «ring12»:

    "testString123".containsSubString(theSubString: "ring12", isCaseSensitive: true) // Returns true
    "testString123".containsSubString(theSubString: "ring12", isCaseSensitive: false) // Returns true
CaOs433
источник