我想拆分一个以纯字符串形式的响应。回应为
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等各种方式拆分响应字符串,但它们都不是更干净的,并且使用多个字符串结果集来逐一解析不整洁的
在字典中拆分响应的任何有用方法。 在上面的响应中,键始终是固定的。
答案 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
,并且word
和key
被value
隔开。 / 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)])
]
}