splitting Swift string complex
I would like to split a response which is in plain string. Response is as
Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead
Need to create a dictionary from this response like, ResultSetDic[String:String]
Status: N/A
Host: somesite.com
is Connection live: true
Status Connection: deny
heart beat: dead
tried splitting the response string with various ways Like NSRegularExpression, Range, Split but none of them is cleaner and working multiple string result sets to parse one by one which is not neat.
Any helpful way to split the response in a dictionary.
In above response keys are always fixed.
ios swift
add a comment |
I would like to split a response which is in plain string. Response is as
Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead
Need to create a dictionary from this response like, ResultSetDic[String:String]
Status: N/A
Host: somesite.com
is Connection live: true
Status Connection: deny
heart beat: dead
tried splitting the response string with various ways Like NSRegularExpression, Range, Split but none of them is cleaner and working multiple string result sets to parse one by one which is not neat.
Any helpful way to split the response in a dictionary.
In above response keys are always fixed.
ios swift
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06
add a comment |
I would like to split a response which is in plain string. Response is as
Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead
Need to create a dictionary from this response like, ResultSetDic[String:String]
Status: N/A
Host: somesite.com
is Connection live: true
Status Connection: deny
heart beat: dead
tried splitting the response string with various ways Like NSRegularExpression, Range, Split but none of them is cleaner and working multiple string result sets to parse one by one which is not neat.
Any helpful way to split the response in a dictionary.
In above response keys are always fixed.
ios swift
I would like to split a response which is in plain string. Response is as
Result Set, Status: N/A Host: somesite.com is Connection live: true Status Connection: deny heart beat: dead
Need to create a dictionary from this response like, ResultSetDic[String:String]
Status: N/A
Host: somesite.com
is Connection live: true
Status Connection: deny
heart beat: dead
tried splitting the response string with various ways Like NSRegularExpression, Range, Split but none of them is cleaner and working multiple string result sets to parse one by one which is not neat.
Any helpful way to split the response in a dictionary.
In above response keys are always fixed.
ios swift
ios swift
edited Nov 19 '18 at 7:37
Cœur
17.8k9106145
17.8k9106145
asked Aug 24 '18 at 16:52
iamMobileiamMobile
54821230
54821230
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06
add a comment |
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06
add a comment |
3 Answers
3
active
oldest
votes
Since you have a fixed format you're parsing, with known keys, and the same format every time, this is a ready made problem for Regular Expressions:
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)])
]
}
add a comment |
The thing what makes this parsable is, that each value
is only a single word
and that key
and value
are separated by :
.
First I identify the the end of the next key, then add the next word as its value.
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
Edit: Array.firstIndex(where:)
seems to be Xcode10+, so in Xcode9.4 you may try:
extension Array {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? {
for index in indices where try predicate(self[index]) { return index }
return nil
}
}
Edit2: A backward-compatible way to add .firstIndex(where:)
from Leo:
extension Collection {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Index? {
return try index(where: predicate)
}
}
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change itindex(of:)
andindex(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
@Purpose better to use the array indices property to iterate through it.for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
|
show 7 more comments
Since you have fixed keys and response format, it might be better go with specific parsing logics with your keys.
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)
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with-> [ResponseParseID: String]
.
– Fabian
Aug 24 '18 at 21:49
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52008779%2fsplitting-swift-string-complex%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Since you have a fixed format you're parsing, with known keys, and the same format every time, this is a ready made problem for Regular Expressions:
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)])
]
}
add a comment |
Since you have a fixed format you're parsing, with known keys, and the same format every time, this is a ready made problem for Regular Expressions:
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)])
]
}
add a comment |
Since you have a fixed format you're parsing, with known keys, and the same format every time, this is a ready made problem for Regular Expressions:
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)])
]
}
Since you have a fixed format you're parsing, with known keys, and the same format every time, this is a ready made problem for Regular Expressions:
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)])
]
}
answered Aug 24 '18 at 23:33
David BerryDavid Berry
31.6k106981
31.6k106981
add a comment |
add a comment |
The thing what makes this parsable is, that each value
is only a single word
and that key
and value
are separated by :
.
First I identify the the end of the next key, then add the next word as its value.
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
Edit: Array.firstIndex(where:)
seems to be Xcode10+, so in Xcode9.4 you may try:
extension Array {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? {
for index in indices where try predicate(self[index]) { return index }
return nil
}
}
Edit2: A backward-compatible way to add .firstIndex(where:)
from Leo:
extension Collection {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Index? {
return try index(where: predicate)
}
}
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change itindex(of:)
andindex(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
@Purpose better to use the array indices property to iterate through it.for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
|
show 7 more comments
The thing what makes this parsable is, that each value
is only a single word
and that key
and value
are separated by :
.
First I identify the the end of the next key, then add the next word as its value.
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
Edit: Array.firstIndex(where:)
seems to be Xcode10+, so in Xcode9.4 you may try:
extension Array {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? {
for index in indices where try predicate(self[index]) { return index }
return nil
}
}
Edit2: A backward-compatible way to add .firstIndex(where:)
from Leo:
extension Collection {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Index? {
return try index(where: predicate)
}
}
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change itindex(of:)
andindex(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
@Purpose better to use the array indices property to iterate through it.for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
|
show 7 more comments
The thing what makes this parsable is, that each value
is only a single word
and that key
and value
are separated by :
.
First I identify the the end of the next key, then add the next word as its value.
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
Edit: Array.firstIndex(where:)
seems to be Xcode10+, so in Xcode9.4 you may try:
extension Array {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? {
for index in indices where try predicate(self[index]) { return index }
return nil
}
}
Edit2: A backward-compatible way to add .firstIndex(where:)
from Leo:
extension Collection {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Index? {
return try index(where: predicate)
}
}
The thing what makes this parsable is, that each value
is only a single word
and that key
and value
are separated by :
.
First I identify the the end of the next key, then add the next word as its value.
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
Edit: Array.firstIndex(where:)
seems to be Xcode10+, so in Xcode9.4 you may try:
extension Array {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Int? {
for index in indices where try predicate(self[index]) { return index }
return nil
}
}
Edit2: A backward-compatible way to add .firstIndex(where:)
from Leo:
extension Collection {
func firstIndex(where predicate: (Element) throws -> Bool) rethrows -> Index? {
return try index(where: predicate)
}
}
edited Aug 24 '18 at 17:53
answered Aug 24 '18 at 17:06
FabianFabian
1,1542514
1,1542514
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change itindex(of:)
andindex(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
@Purpose better to use the array indices property to iterate through it.for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
|
show 7 more comments
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change itindex(of:)
andindex(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
@Purpose better to use the array indices property to iterate through it.for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
Thanks Purpose. I'm unable to see step1.firstIndex. Gettting error in Playground string-operations.playground:161:27: error: value of type '[String.SubSequence]' (aka 'Array<Substring>') has no member 'firstIndex' guard let index = step1.firstIndex(where: { $0.contains(":") }) else {
– iamMobile
Aug 24 '18 at 17:16
change it
index(of:)
and index(where:)
– Leo Dabus
Aug 24 '18 at 17:27
change it
index(of:)
and index(where:)
– Leo Dabus
Aug 24 '18 at 17:27
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
@iamMobile The function seems to have been added in Xcode10/Swift4.2, try the extension above for an alternative. Or try Leo's tip. I can't find them in the Array docs but they may have removed deprecated/renamed functions from it.
– Fabian
Aug 24 '18 at 17:30
1
1
@Purpose better to use the array indices property to iterate through it.
for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
@Purpose better to use the array indices property to iterate through it.
for index in indices where try predicate(self[index]) { return index }
– Leo Dabus
Aug 24 '18 at 17:52
1
1
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
@LeoDabus Damn this makes things short, very nice!
– Fabian
Aug 24 '18 at 17:55
|
show 7 more comments
Since you have fixed keys and response format, it might be better go with specific parsing logics with your keys.
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)
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with-> [ResponseParseID: String]
.
– Fabian
Aug 24 '18 at 21:49
add a comment |
Since you have fixed keys and response format, it might be better go with specific parsing logics with your keys.
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)
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with-> [ResponseParseID: String]
.
– Fabian
Aug 24 '18 at 21:49
add a comment |
Since you have fixed keys and response format, it might be better go with specific parsing logics with your keys.
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)
Since you have fixed keys and response format, it might be better go with specific parsing logics with your keys.
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)
answered Aug 24 '18 at 19:51
HMHeroHMHero
1,920129
1,920129
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with-> [ResponseParseID: String]
.
– Fabian
Aug 24 '18 at 21:49
add a comment |
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with-> [ResponseParseID: String]
.
– Fabian
Aug 24 '18 at 21:49
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with
-> [ResponseParseID: String]
.– Fabian
Aug 24 '18 at 21:49
Interesting approach! Since unknown keys can't be used anyway it makes sense to define them, makes things more sturdy and easier to use with
-> [ResponseParseID: String]
.– Fabian
Aug 24 '18 at 21:49
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52008779%2fsplitting-swift-string-complex%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Where are you getting this data from? Do they have any machine parsable API available? (JSON, XML, YAML, etc.?)
– Alexander
Aug 24 '18 at 16:56
Nope this data is send by a server but in an string format. (Not JSON, i wish it was)
– iamMobile
Aug 24 '18 at 17:06