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?

Gasper J.
  • 481
  • 5
  • 11
  • 2
    I think you should elaborate your example and show us what you have tried. – Rakesha Shastri Feb 04 '19 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 – Gasper J. Feb 04 '19 at 16:35
  • There is something called `firstIndex` now. – Rakesha Shastri Feb 04 '19 at 16:35
  • 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 – Gasper J. Feb 04 '19 at 16:40
  • Thank you @impression7vx I have checked this question before, however I could not find an answer there to how get an index of a given substring – Gasper J. Feb 04 '19 at 17:04
  • 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. – impression7vx Feb 04 '19 at 17:07
  • Is this string in a specific format where every element starts with “Substring #X:” and ends with “;”? – Joakim Danielson Feb 04 '19 at 17:07
  • If I put `let index = textIn.firstIndex(of: subString)`, my Xcode throws an error "Cannot convert value of type 'String' to expected argument type 'Character'"; @JoakimDanielson yes, it is a format for all elements in current array – Gasper J. Feb 04 '19 at 17:20
  • 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. – Joakim Danielson Feb 04 '19 at 17:35
  • @JoakimDanielson I have written lots of code, which does other things but now I am stuck at this moment. By "stuck" I mean I do not even know how to properly start implementing it. I tried one very primitive thing (a for loop, which compares each element `if String[i] == "#" && String[i+1] == num`, but it is very inefficient. my code would run forever in case of a long String – Gasper J. Feb 04 '19 at 17:52
  • I would be glad to show you my code, but I have no code related to this question yet. So, yes, it is a String. I am reading a File into it, so it may be relatively big. My task is to access a substring based on `Substring #` in this big String. thats all I have for now – Gasper J. Feb 04 '19 at 18:15

1 Answers1

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: [])
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 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`? – Gasper J. Feb 04 '19 at 18:04
  • 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. – Sweeper Feb 04 '19 at 18:13
  • @GasperJ. I have edited the most general case into the answer – Sweeper Feb 04 '19 at 18:16