2

I want to create an extension for the String class in Swift that allows you to get a substring via the subscript operator like in Python. This can be accomplished with the Range class in the following way

extension String {

    subscript (range: Range<Int>) -> String? {
        if range.startIndex < 0 || range.endIndex > count(self) {
            return nil
        }
        let range = Range(start: advance(startIndex, range.startIndex), end: advance(startIndex, range.endIndex))
        return substringWithRange(range)
    }
}

This enables the following usage

let string = "OptimusPrime"
string[0...6] // "Optimus"

However, I want to be able to index the string from the end as well as the beginning using negative integers.

string[7...(-1)] // "Prim"

Since the Range class doesn't allow startIndex to be greater than endIndex the extension above is not sufficient to achieve this behavior.

Since Range objects apparently can't be used for this extension, it makes sense to me to simply use the same syntax as in Python

string[0:2] // "Op"
string[0:-1] // "OptimusPrim"

Is this possible? How would I go about doing this?

bjornorri
  • 369
  • 1
  • 3
  • 11

1 Answers1

2

i think you could get python-like syntax like this:

subscript (start:Int, end:Int) -> String?

which would let you go "bla bla"[0,3]

then if you take a negative number in, just make convert it to the string length minus the negative number instead so the range is valid

Fonix
  • 11,447
  • 3
  • 45
  • 74
  • great! subscript is really powerful – LastMove Aug 12 '15 at 08:07
  • This does indeed work and I'll accept this answer since it satisfies my requirements. Let's say however that the subscript with these arguments was reserved for some other purpose such as returning the 2 characters at the given indices. Do you have any ideas about how the colon syntax could be achieved? – bjornorri Aug 12 '15 at 08:10
  • hmm maybe it could take in another argument at the end that is an enum for the functionality it should perform, like "bla bla"[0,3,SUBSTRING], but ye cant really have multiple subscripts with the same number of arguments performing different tasks, but ye then its not python-like anymore anyway so probably not really possible to get it exactly how you want, unless you make it take in a string instead, eg `"bla bla"["0:4"]` then just have to do some string manipulation to get the range, but then it starts getting overly complicated/expensive – Fonix Aug 12 '15 at 08:15
  • dont think it would be possible to get the colon syntax at all either since that just isnt compilable swift code so no hope there im afraid – Fonix Aug 12 '15 at 08:21
  • You could also use a *tuple* parameter: `subscript(range : (Int, Int)) -> String { ... } ; "abcde"[(2,-1)]`. – Martin R Aug 12 '15 at 08:27
  • forgot about tuples, good idea. but then again could be confusing have all these different subscripts that look so similar, would be hard to tell whats going on in your code, so i would suggest rather sticking to one subscript type that is most used, then have the others as normal extension functions – Fonix Aug 12 '15 at 08:35
  • ... or external parameter names: `subscript(#from: Int, #to: Int) ; "abcdefg"[from: 2, to: -1]` ... – Martin R Aug 12 '15 at 08:41