Как обрезать строку с помощью Swift 3

Мой фрагмент кода:

unwanted = " £€₹jetztabfromnow"

let favouritesPriceLabel = priceDropsCollectionView.cells.element(boundBy: UInt(index)).staticTexts[IPCUIAHighlightsPriceDropsCollectionViewCellPriceLabel].label
let favouritesPriceLabelTrimmed = favouritesPriceLabel.components(separatedBy: "jetzt").flatMap { String($0.trimmingCharacters(in: .whitespaces)) }.last

favouritesHighlightsDictionary[favouritesTitleLabel] = favouritesPriceLabelTrimmed

Моя проблема в том, что это не сработало:

let favouritesPriceLabelTrimmed = favouritesPriceLabel.components(separatedBy: unwanted).flatMap { String($0.trimmingCharacters(in: .whitespaces)) }.last

У меня есть цена, как "от 3,95 €" - я хочу сократить все валюты "£€₹" и такие слова, как "от" или "ab"

У вас есть решение для меня, что я могу использовать здесь?

5 ответов

Вместо того, чтобы возиться с попытками заменить или удалить правильные символы или с помощью регулярных выражений, я бы воспользовался встроенной в Фонд поддержкой лингвистических тегов. Это сделает лексический анализ строки и вернет токены различных типов. Используйте его для этого типа строки, и он должен надежно найти любые числа в строке.

Что-то вроде:

var str = "from 3,95 €"

let range = Range(uncheckedBounds: (lower: str.startIndex, upper: str.endIndex))

var tokenRanges = [Range<String.Index>]()

let scheme = NSLinguisticTagSchemeLexicalClass
let option = NSLinguisticTagger.Options()
let tags = str.linguisticTags(in: range, scheme: scheme, options: option, orthography: nil, tokenRanges: &tokenRanges)
let tokens = tokenRanges.map { str.substring(with:$0) }

if let numberTagIndex = tags.index(where: { $0 == "Number" }) {
    let number = tokens[numberTagIndex]
    print("Found number: \(number)")
}

В этом примере код печатает "3,95". Если вы измените str "от 28,50 фунтов стерлингов", он печатает "28,50".

Один из способов - поместить ненужные строки в массив и использовать String replacingOccurrences(of:with:) метод.

let stringToScan = "£28.50"
let toBeRemoved = ["£", "€", "₹", "ab", "from"]
var result = stringToScan
toBeRemoved.forEach { result = result.replacingOccurrences(of: $0, with: "") }
print(result)

... дает "28.50".

Если вы просто хотите извлечь числовое значение с помощью регулярного выражения, оно учитывает запятые или точечные десятичные разделители.

let string = "from 3,95 €"

let pattern = "\\d+[.,]\\d+"
do {
    let regex = try NSRegularExpression(pattern: pattern, options: [])
    if let match = regex.firstMatch(in: string, range: NSRange(location: 0, length: string.utf16.count)) {
        let range = match.range
        let start = string.index(string.startIndex, offsetBy: range.location)
        let end = string.index(start, offsetBy: range.length)
        print(string.substring(with: start..<end)) // 3,95
    } else {
        print("Not found")
    }
} catch {
    print("Regex Error:", error)
}

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

let string = "some initial text 3,95 €" // define the string to scan

// Add a convenience extension to Scanner so you don't have to deal with pointers directly.
extension Scanner {
    func scanDouble() -> Double? {
        var value = Double(0)
        guard scanDouble(&value) else { return nil }
        return value
    }

    // Convenience method to advance the location of the scanner up to the first digit. Returning the scanner itself or nil, which allows for optional chaining
    func scanUpToNumber() -> Scanner? {
        var value: NSString?
        guard scanUpToCharacters(from: CharacterSet.decimalDigits, into: &value) else { return nil }
        return self
    }
}

let scanner = Scanner(string: string)
scanner.locale = Locale(identifier: "fr_FR")
let double = scanner.scanUpToNumber()?.scanDouble() // -> double = 3.95 (note the type is Double?)

Сканеры намного проще в использовании, чем NSRegularExpressions в этих случаях.

Вы можете фильтровать по специальному символу, удалив alphanumerics,

extension String {

    func removeCharacters(from forbiddenChars: CharacterSet) -> String {
        let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
        return String(String.UnicodeScalarView(passed))
    }
}

let str = "£€₹jetztabfromnow12"

let t1 = str.removeCharacters(from: CharacterSet.alphanumerics)
print(t1) // will print: £€₹

let t2 = str.removeCharacters(from: CharacterSet.decimalDigits.inverted)
print(t2) // will print: 12

Обновлено 1:

var str = "£3,95SS"

str = str.replacingOccurrences(of: ",", with: "")

let digit = str.removeCharacters(from: CharacterSet.decimalDigits.inverted)
print(digit) // will print: 395

let currency = str.removeCharacters(from: CharacterSet.alphanumerics)
print(currency) // will print: £

let amount = currency + digit
print(amount) // will print: £3,95

Обновление 2:

let string = "£3,95SS"

let pattern = "-?\\d+(,\\d+)*?\\.?\\d+?"
do {
    let regex = try NSRegularExpression(pattern: pattern, options: [])
    if let match = regex.firstMatch(in: string, range: NSRange(location: 0, length: string.utf16.count)) {
        let range = match.range
        let start = string.index(string.startIndex, offsetBy: range.location)
        let end = string.index(start, offsetBy: range.length)
        let digit = string.substring(with: start..<end)
        print(digit) //3,95

        let symbol = string.removeCharacters(from: CharacterSet.symbols.inverted)
        print(symbol) // £

        print(symbol + digit) //£3,95

    } else {
        print("Not found")
    }
} catch {
    print("Regex Error:", error)
}
Другие вопросы по тегам