拆分Swift字符串复杂

时间:2018-08-24 16:52:30

标签: ios swift

我想拆分一个以纯字符串形式的响应。回应为

Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead

需要根据此响应创建字典,例如ResultSetDic[String:String]

Status: N/A  
Host: somesite.com  
is Connection live: true  
Status Connection: deny  
heart beat: dead  

尝试使用NSRegularExpression,Range,Split等各种方式拆分响应字符串,但它们都不是更干净的,并且使用多个字符串结果集来逐一解析不整洁的

在字典中拆分响应的任何有用方法。 在上面的响应中,键始终是固定的。

3 个答案:

答案 0 :(得分:2)

使之可解析的原因是,每个<table border="1" style="width:100%;"> <thead style="display:fixed"> <th>1</th> <th>2</th> <th>3</th> <th>4</th> </thead> <tbody> <td>A</td> <td colspan="2">B</td> <td>C</td> </tbody> </table> <br/> <table border="1" style="width:100%;"> <thead style="display:none"> <th>1</th> <th>2</th> <th>3</th> <th>4</th> </thead> <tbody> <td>A</td> <td colspan="2">B</td> <td>C</td> </tbody> </table> 仅是单个value,并且wordkeyvalue隔开。 / p>

首先,我确定下一个关键字的结尾,然后添加下一个单词作为其值。

:

编辑:func testing() { let input = "Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead" var step1 = input.split(separator: " ") guard let index = step1.firstIndex(where: { $0.contains(",") }) else { fatalError("Does not contain `,`. at the beginning.") } step1.removeFirst(index + 1) var step2 = step1 var output = [String: String]() repeat { guard let index = step2.firstIndex(where: { $0.contains(":") }) else { // If the last part has no :, can add it under `end`. // output["end"] = step2.joined(separator: " ") step2.removeAll() break } let key = step2[0...index].joined(separator: " ").trimmingCharacters(in: CharacterSet(charactersIn: ":")) let value = step2[index + 1] output [key] = String(value) step2.removeFirst(index + 2) } while step2.count != 0 output.forEach{ print("\($0.key): \($0.value)") } } // Output: // Host: somesite.com // Status Connection: deny // Status: N/A // heart beat: dead // is Connection live: true 似乎是Xcode10 +,所以在Xcode9.4中,您可以尝试:

Array.firstIndex(where:)

Edit2:一种向后兼容的方法,用于从Leo添加extension Array { func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? { for index in indices where try predicate(self[index]) { return index } return nil } }

.firstIndex(where:)

答案 1 :(得分:1)

由于您具有固定的键和响应格式,因此最好将特定的解析逻辑与键一起使用。

let response = "Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead"

enum ResponseParseId: String {
    case status = "Status:"
    case host = "Host:"
    case isConnectionLive = "is Connection live:"
    case statusConnection = "Status Connection:"
    case heartBeat = "heart beat:"

    var key: String {
        switch self {
        case .status:
            return "Status"
        case .host:
            return "Host"
        case .isConnectionLive:
            return "is Connection live"
        case .statusConnection:
            return "Status Connection"
        case .heartBeat:
            return "heart beat"
        }
    }

    static var allIds: [ResponseParseId] = [.status, .host, .isConnectionLive, .statusConnection, .heartBeat]
}

func getValue(from response: String, for key: ResponseParseId) -> String? {
    let components = response.components(separatedBy: key.rawValue)
    if let substring = components.last?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) {
        let subcomponents = substring.components(separatedBy: " ")
        if let value = subcomponents.first {
            return value
    }
}
return nil
}

func getResponseDictionary(response: String) -> [String: String] {
    var dictionary: [String: String] = [:]
    for id in ResponseParseId.allIds {
        if let value = getValue(from: response, for: id) {
            dictionary[id.key] = value
        }
    }
        return dictionary
    }

let dictionary = getResponseDictionary(response: response)

print(dictionary)

答案 2 :(得分:1)

由于您要解析的格式是固定的,并且具有已知的键,并且每次都使用相同的格式,所以这是正则表达式的现成问题:

let input = "Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead"

extension String {
    subscript(range:NSRange) -> Substring {
        let start = index(startIndex, offsetBy: range.location)
        let end = index(start, offsetBy: range.length)

        return self[start..<end]
    }
}

func parse(response:String) -> [String:String]? {
    guard let regex = try? NSRegularExpression(pattern: "Result Set, Status: (.*) Host: (.*) is Connection live: (.*) Status Connection: (.*) heart beat: (.*)", options:[]) else {
        return nil
    }

    guard let match = regex.firstMatch(in: input, range:NSRange(input.startIndex..<input.endIndex, in: input)) else {
        return nil
    }

    // Note that a much better approach here would be to *not* return
    //  a dictionary, but instead to return a struct containing all
    //  of the relevant data
    return [
        "Status": String(input[match.range(at: 1)]),
        "Host": String(input[match.range(at:2)]),
        "is Connection live": String(input[match.range(at:3)]),
        "Status Connection": String(input[match.range(at: 4)]),
        "heart beat": String(input[match.range(at:5)])
    ]
}