Я еще не смог выяснить, как получить подстроку String
в Swift:
var str = “Hello, playground”
func test(str: String) -> String {
return str.substringWithRange( /* What goes here? */ )
}
test (str)
Я не могу создать диапазон в Swift. Автозаполнение на игровой площадке не очень полезно - вот что он предлагает:
return str.substringWithRange(aRange: Range<String.Index>)
В стандартной справочной библиотеке Swift я не нашел ничего, что могло бы помочь. Вот еще одна дикая догадка:
return str.substringWithRange(Range(0, 1))
И это:
let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)
Я видел другие ответы ( Поиск индекса символа в Swift String ), которые, кажется, предполагают, что, поскольку String
это тип моста для NSString
«старых» методов, они должны работать, но неясно, как - например, это тоже не работает ( неверный синтаксис):
let x = str.substringWithRange(NSMakeRange(0, 3))
Мысли?
Ответы:
Вы можете использовать метод substringWithRange. Требуется начало и конец String.Index.
Чтобы изменить начальный и конечный индексы, используйте advancedBy (n).
Вы также можете по-прежнему использовать метод NSString с NSRange, но вы должны убедиться, что вы используете NSString следующим образом:
Примечание: как упоминалось в JanX2, этот второй метод небезопасен со строками Unicode.
источник
advance
означает, что мы должны пройти весь путь через возможно длинную строку. Но формирование NSRange и использование NSString явно опасно? Что осталось?Swift 2
просто
Свифт 3
Swift 4
substring(to:)
иsubstring(from:)
устарели вSwift 4
.источник
ПРИМЕЧАНИЕ: @airspeedswift делает несколько очень проницательных замечаний о компромиссах этого подхода, особенно о скрытом на производительность. Строки не простые звери, и получение определенного индекса может занять O (n) времени, что означает, что цикл, использующий нижний индекс, может быть O (n ^ 2). Вы были предупреждены.
Вам просто нужно добавить новую
subscript
функцию, которая принимает диапазон и используетadvancedBy()
для перехода туда, куда вы хотите:(Это определенно должно быть частью языка. Пожалуйста, дупе рдар: // 17158813 )Для развлечения вы также можете добавить
+
оператор в индексы:(Я пока не знаю, должен ли этот быть частью языка или нет.)
источник
advance<T>(…)
вSwift
пространстве имен.String.Index
. В этом случае это не столько оптимизация, сколько простота. Необходимость манипулирования между int и String.Index взад и вперед повсюду приведет к путанице.String.Index
es), что часто имеет место. Чем вы можете пожелать, чтобы все эти методы обработки строк работали сInt
s. И вы вынуждены преобразовать это,String.Indexes
что приводит к беспорядку, который вы упомянули.На момент написания статьи ни одно расширение не было полностью совместимо с Swift 4.2 , так что вот оно, которое покрывает все потребности, которые я мог придумать:
И тогда вы можете использовать:
string.substring(from: 1, to: 7)
получает вас:ello,Wo
string.substring(to: 7)
получает вас:Hello,Wo
string.substring(from: 3)
получает вас:lo,World!
string.substring(from: 1, length: 4)
получает вас:ello
string.substring(length: 4, to: 7)
получает вас:o,Wo
Обновлено
substring(from: Int?, length: Int)
для поддержки, начиная с нуля.источник
"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14)
дает нам:o😇😍😘😎📸📀💾∝ℵℶ
SWIFT 2.0
просто:
SWIFT 3.0
SWIFT 4.0
Операции с подстрокой возвращают экземпляр типа Substring вместо String.
источник
text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
Это намного проще, чем любой из ответов здесь, если вы найдете правильный синтаксис.
Я хочу забрать [и]
Результатом будет "ABCDEFGHI", startIndex и endIndex также могут быть использованы в
и так далее!
PS: как указано в комментариях, есть некоторые синтаксические изменения в swift 2, который поставляется с xcode 7 и iOS9!
Пожалуйста, посмотрите на эту страницу
источник
advance(myString.endIndex, -1)
синтаксис Xcode 7 beta 6 изменился наmyString.endIndex.advancedBy(-1)
Например, чтобы найти имя (до первого пробела) в моем полном имени:
start
иend
имеют типString.Index
здесь и используются для созданияRange<String.Index>
и используются в индексном методе доступа (если пробел вообще найден в исходной строке).Трудно создать
String.Index
непосредственно из целочисленной позиции, как в первом посте. Это потому, что на мое имя каждый символ будет иметь одинаковый размер в байтах. Но символы, использующие специальные акценты в других языках, могли бы использовать еще несколько байтов (в зависимости от используемой кодировки). Так к какому байту должно относиться целое число?Можно создать новый
String.Index
из существующего, используя методыsucc
иpred
который будет гарантировать, что правильное количество байтов будет пропущено для перехода к следующей точке кода в кодировке. Однако в этом случае проще найти индекс первого пробела в строке, чтобы найти конечный индекс.источник
Для меня это действительно интересная часть вашего вопроса. Строка является мостиком NSString, поэтому большинство методов NSString сделать работу непосредственно на String. Вы можете использовать их свободно и не задумываясь. Так, например, это работает так, как вы ожидаете:
Но, как это часто бывает, «у меня работает мой моджо, но он не работает на вас» Вы просто выбрали один из редких случаев, когда существует параллельный метод Swift с тем же именем , и в таком случае метод Swift затмевает метод Objective-C. Таким образом, когда вы говорите
str.substringWithRange
, Swift думает, что вы имеете в виду метод Swift, а не метод NSString - и тогда вы попадаете в ловушку, потому что метод Swift ожидаетRange<String.Index>
, и вы не знаете, как создать один из них.Самый простой выход состоит в том, чтобы остановить Swift от затенения следующим образом:
Обратите внимание, что здесь не требуется никакой дополнительной работы. «В ролях» не означает «конвертировать»; струнный это фактически является NSString. Мы просто говорим Swift, как выглядеть на эту переменную для целей этой единственной строки кода.
Действительно странной частью всего этого является то, что метод Swift, который вызывает все эти проблемы, не имеет документов. Я понятия не имею, где это определено; его нет в заголовке NSString и нет в заголовке Swift.
источник
Range<String.Index>
, либо убрать этот недокументированный метод с нашего пути.В новом Xcode 7.0 используйте
источник
.advancedBy(0)
не обязательно для startIndex.Короткий ответ: сейчас это очень сложно в Swift. Я догадываюсь, что Apple еще предстоит проделать большую работу над удобными методами для таких вещей.
String.substringWithRange()
ожидаетRange<String.Index>
параметр, и, насколько я могу судить, нет метода генератора дляString.Index
типа. Вы можете получитьString.Index
значения отaString.startIndex
иaString.endIndex
и позвонить.succ()
или.pred()
на них, но это безумие.Как насчет расширения класса String, которое принимает старые добрые
Int
s?Обновление: Swift beta 4 решает следующие проблемы!
В его нынешнем виде [в бета-версии 3 и более ранних версиях] даже у строк Swift есть проблемы с обработкой символов Юникода. Значок собаки выше работал, но следующее не работает:
Вывод:
источник
NSString
заставило меня думать, что я использовал только нативныеString
методы Swift , так как я не использовал никакихmyString as NSString
вызовов.Вы можете использовать эти расширения для улучшения
substringWithRange
Swift 2.3
Свифт 3
Использование:
источник
Пример кода для получения подстроки в Swift 2.0
(i) Подстрока из начального индекса
Входные данные: -
Вывод:-
(ii) Подстрока из определенного индекса
Входные данные: -
Вывод:-
Я надеюсь, что это поможет вам!
источник
Простое решение с небольшим кодом.
Создайте расширение, включающее базовую подстроку, которую имеют почти все другие языки:
Просто позвоните с
источник
Это работает на моей детской площадке :)
источник
advance
Обновлено для Xcode 7. Добавляет расширение String:
Использование:
Реализация:
источник
попробуйте это на детской площадке
это даст вам "привет, р"
Однако, где это становится действительно интересным, это то, что если вы сделаете последний индекс больше, чем строка на площадке, он покажет все строки, которые вы определили после str: o
Range (), похоже, является универсальной функцией, поэтому ей нужно знать тип, с которым она имеет дело.
Вы также должны дать ему фактическую строку, которая вас интересует игровыми площадками, так как кажется, что она содержит все строки в последовательности один за другим с последующим именем переменной.
Так
дает "Привет, детская площадка" str Я следующая строка "str2 "
работает, даже если str2 определен с помощью let
:)
источник
Роб Напье уже дал потрясающий ответ, используя нижний индекс. Но я почувствовал один недостаток в этом, поскольку нет проверки на выход из связанных условий. Это может привести к краху. Так что я изменил расширение и вот оно
Выход ниже
Так что я предлагаю всегда проверять, если позволить
источник
В Swift3
Например: переменная «Герцог Джеймс Томас», нам нужно получить «Джеймс».
источник
Взяв страницу от Rob Napier, я разработал эти Common String Extensions , два из которых:
Использование:
источник
Range
вместоRange<String.Index>
благодаря выводу типа.Вот как вы получаете диапазон из строки:
Ключевым моментом является то, что вы передаете диапазон значений типа String.Index (это то, что возвращает аванс) вместо целых чисел.
Причина, по которой это необходимо, заключается в том, что строки в Swift не имеют произвольного доступа (в основном из-за переменной длины символов Unicode). Вы также не можете сделать
str[1]
. String.Index предназначен для работы с их внутренней структурой.Однако вы можете создать расширение с индексом, который сделает это за вас, так что вы можете просто передать диапазон целых чисел (см., Например , ответ Роба Нейпира ).
источник
Я пытался придумать что-нибудь Pythonic.
Все подписки здесь замечательные, но в те времена, когда я действительно нуждаюсь в чем-то простом, обычно я хочу отсчитать со спины
string.endIndex.advancedBy(-1)
Он поддерживает
nil
значения как для начала, так и для конца индекса, гдеnil
будет означать индекс в 0 для начала,string.characters.count
для конца.РЕДАКТИРОВАТЬ
Более элегантное решение:
источник
Сначала создайте диапазон, затем подстроку. Вы можете использовать
fromIndex..<toIndex
синтаксис так:источник
Вот пример получения только идентификатора видео .ie (6oL687G0Iso) из всего URL в swift
источник
Полный образец вы можете увидеть здесь
источник
http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ показывает, что это работает хорошо:
источник
Ну, у меня была та же проблема, и я решил ее с помощью функции bridgeToObjectiveC ():
Обратите внимание, что в этом примере substringWithRange вместе с NSMakeRange принимают участие в строке, начиная с индекса 6 (символ «W») и заканчивая индексом 6 + 6 позиций вперед (символ «!»)
Приветствия.
источник
Вы можете использовать любой из методов подстроки в расширении Swift String, которое я написал https://bit.ly/JString .
источник
Если у вас есть
NSRange
, мостNSString
работает без проблем. Например, я немного поработалUITextFieldDelegate
и быстро захотел вычислить новое строковое значение, когда он спросил, должен ли он заменить диапазон.источник
Простое расширение для
String
:источник
Если вам не важна производительность ... это, вероятно, самое лаконичное решение в Swift 4
Это позволяет вам сделать что-то вроде этого:
источник