Сложное расширение Swift

Я хочу создать расширение для класса String в Swift, которое позволит вам получить подстроку с помощью оператора индекса, как в Python. Это можно сделать с помощью класса Range следующим образом.

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)
    }
}

Это позволяет использовать следующее

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

Однако я хочу иметь возможность индексировать строку как с конца, так и с начала, используя отрицательные целые числа.

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

Поскольку класс Range не допускает, чтобы startIndex превышало endIndex, приведенного выше расширения недостаточно для достижения такого поведения.

Поскольку объекты Range, по-видимому, не могут использоваться для этого расширения, мне имеет смысл просто использовать тот же синтаксис, что и в Python.

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

Это возможно? Как мне это сделать?


person bjornorri    schedule 12.08.2015    source источник


Ответы (1)


я думаю, вы могли бы получить синтаксис, подобный python, следующим образом:

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

что отпустило бы тебя "bla bla"[0,3]

затем, если вы возьмете отрицательное число, просто преобразуйте его в длину строки за вычетом отрицательного числа, чтобы диапазон был действительным

person Fonix    schedule 12.08.2015
comment
большой! индекс действительно мощный - person LastMove; 12.08.2015
comment
Это действительно работает, и я приму этот ответ, поскольку он удовлетворяет моим требованиям. Предположим, однако, что индекс с этими аргументами был зарезервирован для какой-то другой цели, например, для возврата двух символов по заданным индексам. Есть ли у вас какие-либо идеи о том, как можно реализовать синтаксис двоеточия? - person bjornorri; 12.08.2015
comment
хм, возможно, он мог бы принять еще один аргумент в конце, который является перечислением функций, которые он должен выполнять, например, bla bla[0,3,SUBSTRING], но на самом деле вы не можете иметь несколько индексов с одинаковым количеством аргументов, выполняющих разные задачи, но тогда он все равно больше не похож на python, поэтому, вероятно, на самом деле невозможно получить его именно так, как вы хотите, если только вы не заставите его вместо этого принимать строку, например, "bla bla"["0:4"], тогда просто нужно выполнить некоторые манипуляции со строками, чтобы получить диапазон, но затем это становится слишком сложным/дорогим - person Fonix; 12.08.2015
comment
не думаю, что вообще можно было бы получить синтаксис двоеточия, так как это просто не компилируемый быстрый код, так что нет надежды, я боюсь - person Fonix; 12.08.2015
comment
Вы также можете использовать параметр tuple: subscript(range : (Int, Int)) -> String { ... } ; "abcde"[(2,-1)]. - person Martin R; 12.08.2015
comment
забыл про кортежи, хорошая идея. но опять же может сбить с толку все эти разные индексы, которые выглядят так похоже, было бы трудно сказать, что происходит в вашем коде, поэтому я бы предложил придерживаться одного типа индекса, который наиболее часто используется, а затем использовать другие как обычное расширение функции - person Fonix; 12.08.2015
comment
... или имена внешних параметров: subscript(#from: Int, #to: Int) ; "abcdefg"[from: 2, to: -1] ... - person Martin R; 12.08.2015