2

I have to parse these type of strings:

let result1 = "t=20171017T1201&s=349.00&fn=8712000100030779&i=21456&fp=124519970&n=1"
let result2 = "t=20171016T180757&s=92.00&fn=8710000101140572&i=17711&fp=4191934636&n=1"

I need to somehow extract t and fn parameters and save them to another string:

print(t1)    // 20171017T1201
print(fn1)   // 8712000100030779
print(t2)    // 20171016T180757
print(fn2)   // 8710000101140572

I managed to get those parameters by checking the whole string symbol by symbol, but there must be a better way to do so.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Maxim Skryabin
  • 385
  • 2
  • 11
  • 1
    Possible duplicate of [Swift - Get URL Parameters](https://stackoverflow.com/questions/41421686/swift-get-url-parameters). – Martin R Nov 02 '17 at 11:06
  • Possible duplicate of [swift 3 get a substring from query params](https://stackoverflow.com/questions/46160472/swift-3-get-a-substring-from-query-params). – Martin R Nov 02 '17 at 12:03

4 Answers4

3

You need to use the components(separatedBy: _) to split the string into parsable pairs.

let result1 = "t=20171017T1201&s=349.00&fn=8712000100030779&i=21456&fp=124519970&n=1"
let result2 = "t=20171016T180757&s=92.00&fn=8710000101140572&i=17711&fp=4191934636&n=1"

func value(for name: String, in query: String) -> String? {
    for params in query.components(separatedBy: "&") {
        let pair = params.components(separatedBy: "=")
        if (pair.first == name) { 
            return pair.last
        }
    }
    return nil
}

print(value(for: "t", in: result1))
print(value(for: "fn", in: result1))
print(value(for: "t", in: result2))
print(value(for: "fn", in: result2))
Callam
  • 11,409
  • 2
  • 34
  • 32
2

Based on the fact that those strings are basically query parameters of an URL, you can use the following hack to get it quite easily:

let result1 = "t=20171017T1201&s=349.00&fn=8712000100030779&i=21456&fp=124519970&n=1"
let result2 = "t=20171016T180757&s=92.00&fn=8710000101140572&i=17711&fp=4191934636&n=1"

let params1 = queryParameters(from: result1)
let params2 = queryParameters(from: result2)

if let t1 = params1["t"], let t2 = params2["t"] {
    print(">>> t1 - \(t1) t2 - \(t2)")
}


public func queryParameters(from parameters: String) -> [String: String] {
    var components = URLComponents()
    components.query = parameters
    guard
        let queryItems = components.queryItems else {
            return [:]
    }

    var parameters = [String: String]()
    for item in queryItems {
        parameters[item.name] = item.value
    }

    return parameters
}
Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
1

it would create a little workaround here, URLComponents can help to you in this case as your input seems a standard query string to me (see RFC-3986).

let result1: String = "t=20171017T1201&s=349.00&fn=8712000100030779&i=21456&fp=124519970&n=1"

so I would take advantages of that and expect working with an array of URLQueryItem, so this extension has been placed on an array (maybe not effective but quite straightforward).

extension Array where Iterator.Element == URLQueryItem {

    subscript(key: String) -> String? {
        get {
            return self.filter { $0.name == key }.first?.value
        }
    }

}

then I would just read the components from a randomly generated but syntactically valid URL in any random order:

if let url = URL(string: "u://?\(result1)"),
    let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {

    // ...

    let t: String? = urlComponents.queryItems?["t"] // "20171017T1201"
    let s: String? = urlComponents.queryItems?["s"] // "349.00"
    let fp: String? = urlComponents.queryItems?["fp"] // "124519970"
    let random: String? = urlComponents.queryItems?["random"] // nil

    // ...
}

NOTE: this solution is based on the nature of your input string (query-string), if the input format changes in future, you may need to use regular expressions directly to extract information.

Community
  • 1
  • 1
holex
  • 23,961
  • 7
  • 62
  • 76
0

You could implement it like:

if let t1 = result1.components(separatedBy: "t=")[1].components(separatedBy: "&").first {
    print(t1) // 20171017T1201
}

if let fn1 = result1.components(separatedBy: "fn=")[1].components(separatedBy: "&").first {
    print(fn1) // 8712000100030779
}

Note that if you are pretty sure that your string are URL parameters, I would recommend to follow @Milan Nosáľ answer.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143