swift String + character + Range There is no way to to work with Ranges?

the challenge:


presented with a String : "\"someText\" moretext \" \" +\"text\"" - don't ask,

the goal is to find all of the blocks of text terminated by quotes, and make an [Range<String.index] of those ranges.


here's the issue:

you can't just find quotes. you need to find the first quote, then the second quote, and build a Range<String.index>, Add that to an array, and Bob's yer uncle.

here are the problems:

1. you cannot make a Range<String.index> from the startindex, and endindex of 2 ranges.

2. there is no apparent way to get the distance between two ranges, so... you can't use advance(startIndex, N)


So we try to do everything with NSString. Which is an appaling sensation of failure, btw... this should be easy, but this unicode stuff was designed by eggheads who never had to use it. but Swift plays a cruel joke that fubars EVERYTHING. rangeOfString(String) only returns type Range<String.index>... NSString is blocked, can't be used, and the other option is not yet complete.


so... I try to get the String.characters and treat it like an array. String.characters, is Not an array. I can "for in' them, but it's not an actual array.


I get it. Unicode is the future, but why did the present have to be murdered in cold blood? Nothing actually works. and: can you think of any workarounds?

Answered by OOPer in 43971022

Sorry, if I'm missing some of the restrictions you have in this issue.

But, this code can retrun [Range<String.Index>]:

var str = "\"someText\" moretext  \" \" +\"text\""
var ranges: [Range<String.Index>] = []
var start: String.Index? = nil
for index in str.characters.indices where str.characters[index] == "\"" {
    if let startIndex = start {
        ranges.append(startIndex..<index)
        start = nil
    } else {
        start = index.successor()
    }
}
guard start == nil else {
    fatalError("unterminated quote")
}
var strArr = ranges.map {str[$0]} //->["someText", " ", "text"]


Or if you prefer using rangeOfString, you can write something like this:

ranges = []
start = nil
var currentPos: String.Index = str.startIndex
while let range = str.rangeOfString("\"", options: [], range: currentPos..<str.endIndex, locale: nil) {
    if let startIndex = start {
        ranges.append(startIndex..<range.startIndex)
        start = nil
    } else {
        start = range.endIndex
    }
    currentPos = range.endIndex
}
Accepted Answer

Sorry, if I'm missing some of the restrictions you have in this issue.

But, this code can retrun [Range<String.Index>]:

var str = "\"someText\" moretext  \" \" +\"text\""
var ranges: [Range<String.Index>] = []
var start: String.Index? = nil
for index in str.characters.indices where str.characters[index] == "\"" {
    if let startIndex = start {
        ranges.append(startIndex..<index)
        start = nil
    } else {
        start = index.successor()
    }
}
guard start == nil else {
    fatalError("unterminated quote")
}
var strArr = ranges.map {str[$0]} //->["someText", " ", "text"]


Or if you prefer using rangeOfString, you can write something like this:

ranges = []
start = nil
var currentPos: String.Index = str.startIndex
while let range = str.rangeOfString("\"", options: [], range: currentPos..<str.endIndex, locale: nil) {
    if let startIndex = start {
        ranges.append(startIndex..<range.startIndex)
        start = nil
    } else {
        start = range.endIndex
    }
    currentPos = range.endIndex
}

That's great. Thanks.

This stuff is gibberish to me. where can I find documentation?

also, I saw what you did about unterminated quotes.

Reading official documentations of String.CharacterView.Index or such made little use...

Needed try and error, and re-try and re-error, and so on. (I have been struggling with Swift to write some sort of syntax parser.)

For me, it seems Swift needs a documentation of String handling.

I don't think that is a good example of using Swift guard. Just wanted to show that you can check unterminated quote by `start` not being nil.

swift String &#43; character &#43; Range There is no way to to work with Ranges?
 
 
Q