0

I checked lots of similar questions here, the answers to which do not seem to be a working solution for me. I am reading a formatted File into a string "Substring #1: Hello World!; Substring #2: My name is Tom; Substring #X: This is another substring". I need to find an index of Substring #1 to print its content (Hello World!), later in code I would need to print the content of Substring #2 (My name is Tom) and so on.

So far I have tried:

String.index(of: subString) - Xcode error:

Cannot convert value of type 'String' to expected argument type 'Character'

String.firstIndex(of: subString) - Xcode error: `

Cannot convert value of type 'String' to expected argument type 'Character'

What would the efficient way of doing this?

11
  • 2
    I think you should elaborate your example and show us what you have tried. Commented Feb 4, 2019 at 16:32
  • I have found String.index(of: "subString"), however this does not work in Swift 4; String.range(of: "subString") returns a long piece of code while I need an index Commented Feb 4, 2019 at 16:35
  • There is something called firstIndex now. Commented Feb 4, 2019 at 16:35
  • 1
    Can you show us what you have done? You say you "It seems to be accepting only Characters, which is fine for Substring #1 ... Substring #9 however I can not use it if the String contains Substring #10 and bigger " however, we don't see this. Commented Feb 4, 2019 at 17:07
  • 1
    So the substrings are already in an array? Because that was what I was going to suggest to make it easier, split the string and put the parts in an array. It would really help if you supplied a little more information about what you have perhaps with some code. Commented Feb 4, 2019 at 17:35

1 Answer 1

0

You can use a regex to match your string, assuming that all substrings end with either a ; or the end of string.

This is the regex you should use:

Substring #(\d+): (.+?)(?:;|$)

It captures the substring number into group 1 and the substring into group 2.

You can use it like this:

extension String {
    func substring(withNSRange range: NSRange) -> String {
        return String(string[Range(range, in: self)!])
    }
}

let string = "Substring #1: Hello World!; Substring #2: My name is Tom"
let regex = try! NSRegularExpression(pattern: "Substring #(\\d+): (.+?)(?:;|$)", options: [])
let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
let tuples = matches.map { (Int(string.substring(withNSRange: $0.range(at: 1))), string.substring(withNSRange: $0.range(at: 2))) }
let dict = Dictionary(uniqueKeysWithValues: tuples)

// dict will contain something like [1: Hello World!, 2: My name is Tom]

Edit:

Assuming that the custom end of substring is stored in a variable called customStringEnd, you can create the regex like this:

let regex = try! NSRegularExpression(pattern: "Substring #(\\d+): (.+?)(?:\(NSRegularExpression.escapedPattern(for: customStringEnd))|$)", options: [])
Sign up to request clarification or add additional context in comments.

3 Comments

I am really new to programming and especially to Swift. Can you please show me what would I need to modify in your code in case the substrings end with another symbols, e.g. </, || or customSubstringEnd?
See the ; at the end of the regex? Just replace that with the end of string. Remember to escape characters that have special meaning in regex, such as |. For </, it would be Substring #(\d+): (.+?)(?:</|$). For ||, it would be Substring #(\d+): (.+?)(?:\|\||$). @GasperJ.
@GasperJ. I have edited the most general case into the answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.