can I split a numeric string using multiple separa

2019-01-15 22:27发布

I have a string array with fractional numbers and decimal numbers.

    let stringArray = [ "0.0", "193.16", "5/4", "503.42", "696.58", "25/16", "1082.89", "2/1"]

Each array element is mapped in a closure where numbers are extracted from the string.

    let values = stringArray.map { s -> Double in

either fractional (see earlier post)

    let splitStrings = s.characters.split(separator: "/").map(String.init).map({ Double($0) })

or decimal

    let splitStrings = s.characters.split(separator: ".").map(String.init).map({ Double($0) })

Question: In Swift is there a way to split the string using more than one separator so a single closure can return fractional values or decimal values ?

(continuation of closure)

switch (token)) {
case "/"  :
        print( "fraction")

        let pathA = splitString[0]!/splitString[1]!
        return pathA

case "."  :
        print( "decimal")

        let upperSplit = splitString[0]!
        let lowerSplit = splitString[1]! * 0.1  // restore decimal point
        let pathB = upperSplit+lowerSplit
        return pathB
        }
}

3条回答
Lonely孤独者°
2楼-- · 2019-01-15 22:49

If your intention is to create floating point numbers from either a decimal representation or a fraction, then there is no need to split the string at the decimal point.

You can try to convert the string with Double(string), and if that fails, split it at the slash and convert numerator and denominator separately:

func doubleFromDecimalOrFraction(s: String) -> Double? {
    // Try to convert from decimal representation:
    if let value = Double(s) {
        return value
    }
    // Try to convert from fractional format:
    if let range = s.range(of: "/"),
        let num = Double(s.substring(to: range.lowerBound)),
        let den = Double(s.substring(from: range.upperBound)) {
        return num/den
    }
    // Invalid format
    return nil
}

(Instead of returning nil for invalid input you might also consider to throw an error, to abort the execution with fatalError(), or to return some default value.)

This "utility function" can then be applied each array element:

let strings = [ "0.0", "193.16", "5/4", "503.42", "696.58", "25/16", "1082.89", "2/1"]
let values = strings.flatMap(doubleFromDecimalOrFraction)
查看更多
唯我独甜
3楼-- · 2019-01-15 22:56

Split by more than one separator

Using split

Swift 4

let s = "[0, 1, 2, 1]"
let splitted = s.characters.split { [",", "[", "]"].contains($0.description) }

Swift 3

let s = "[0, 1, 2, 1]"
let splitted = s.characters.split { [",", "[", "]"].contains($0.description) }

Swift 2

let s = "[0, 1, 2, 1]"
let splitted = s.characters.split(isSeparator: {[",", "[", "]"].contains($0)}) }

Using characterSet

Swift 4

let str = "[0, 1, 2, 1]"
let separatorSet = CharacterSet(charactersIn: ",[]")
let comps = str.components(separatedBy: separatorSet)

Swift 3

let str = "[0, 1, 2, 1]"
let separatorSet = CharacterSet(charactersInString: ",[]")
let comps = str.components(separatedBy: separatorSet)

Swift 2

let str = "[0, 1, 2, 1]"
let separatorSet = NSCharacterSet(charactersInString: ",[]")
let comps = str.componentsSeparatedByCharactersInSet(separatorSet)

No matter what method we will use, and as a result, you will receive array. Without the information, which separator was used

If you need only convert String to Double then

let array = stringArray.compactMap { element -> Double? in
    if let value = Double(element) {
        return value
    }
    let parts = element.components(separatedBy: "/")
    guard parts.count == 2, 
          let dividend = Double(parts[0]), 
          let divisor = Double(parts[1]), 
          divisor != 0
    else {
        return nil
    }
    return dividend / divisor
}
查看更多
劫难
4楼-- · 2019-01-15 22:56

Define extension (Swift 4):

extension String {
    func split(separators: String) -> [String] {
        return components(separatedBy: CharacterSet(charactersIn: separators))
    }
}

Usage:

let str = "aaa-bbb_ccc/ffffd"
let arr = str.split(separators: "-_/")

Result :

["aaa", "bbb", "ccc", "ffffd"]

查看更多
登录 后发表回答