Быстрая версия компонентовSeparatedByString
Я знаю его вопрос noob, я действительно ищу вокруг, прежде чем спросить. Но нет точного ответа на то, что я хочу знать.
Как мы разделяем строку в массив без использования Objective C? Например:
var str = "Today is so hot"
var arr = str.componentsSeparatedByString(" ") // *
- Я знаю, что это не работает, но я так ищу. Я хочу разбить строку на "" (или другую char/string)
Идея: Это может быть очень хорошо для меня, делая расширение класса string. Но я не знаю, как это сделать.
Изменить: Забыть import Foundation. Если я импортирую фундамент, он будет работать. Но есть ли способ расширить класс String?
Спасибо вам
Ответы
Ответ 1
Если вы хотите разбить строку на заданный символ, вы можете использовать
встроенный split()
метод, без необходимости создания:
let str = "Today is so hot"
let arr = split(str, { $0 == " "}, maxSplit: Int.max, allowEmptySlices: false)
println(arr) // [Today, is, so, hot]
Обновление для Swift 1.2: Порядок изменения параметров с помощью Swift 1.2 (Xcode 6.3), сравните split теперь жалуется на отсутствие "isSeparator "" :
let str = "Today is so hot"
let arr = split(str, maxSplit: Int.max, allowEmptySlices: false, isSeparator: { $0 == " "} )
println(arr) // [Today, is, so, hot]
Обновление для Swift 2: См. Ответ Стюарта.
Обновление для Swift 3:
let str = "Today is so hot"
let arr = str.characters.split(separator: " ").map(String.init)
print(arr)
Ответ 2
В Swift 2 синтаксис для этого стал более кратким. Функция split
верхнего уровня теперь представляет собой метод на CollectionType
(который соответствует String.CharacterView
).
Существует две версии метода: первая принимает замыкание как предикат, чтобы указать, следует ли рассматривать данный элемент как разделитель, а другой просто берет элемент для указания в качестве разделителя - это, скорее всего, то, что вы хотите на 99% разрывов строк. У них обоих есть пара дефолтных параметров (подробности см. В документах), что помогает сохранить хороший вызов метода.
Стоит отметить, что split(_:)
возвращает SubSequence
(в основном a Slice
), поэтому в большинстве случаев требуется преобразовать обратно в массив String
, который обычно более полезен.
let str = "Today is so hot"
let words = str.characters.split(" ").map { String($0) } // or `.map(String.init)`
Объяснение выражения строкового инициализатора (map(String.init)
)
map
- это метод, который принимает функцию как аргумент. В большинстве случаев вы, вероятно, просто используете закрывающее закрытие (неназванная функция) в качестве аргумента map
, например:
func createString(from character: Character) -> String {
// ...
}
let strings = characters.map { createString(from: $0) }
Но следующее более кратким и справедливым:
let strings = characters.map(createString(from:))
// or even:
let strings = characters.map(createString) // argument names inferred from context.
В приведенном выше примере createString(from:)
и createString
являются функциональными выражениями. map
ожидает функцию как аргумент, и в качестве аргумента можно передать выражение функции. Вы можете передать выражение функции в любом месте, которое принимает функцию как аргумент, поэтому вы можете использовать sort
как это для типов, соответствующих Comparable
:
let sortedStrings = strings.sorted(by: <)
// `<` is just a function expression for a function that is essentially declared something like this:
func <(lhs: String, rhs: String) -> Bool {
// ...
}
String.init
является выражением инициализатора. Его можно использовать точно так же, как выражение функции - он сам описывает функцию, которая принимает один Character
в качестве аргумента и возвращает значение типа String
(хотя String.init
перегружен и может быть прошло много разных аргументов).
Чтобы уточнить, что происходит, рассмотрите следующий код, где каждый вызов map
выполняет точно то же самое, но использует все более сжатый синтаксис:
// - Closure expression syntax used.
// - Explicit argument names & types.
// - Long-hand string initialization.
let strings = characters.map({ (character: CharacterView) -> String in
return String.init(character)
})
// - Trailing closure syntax used (parentheses omitted).
// - Closure argument and return types inferred from context (type names omitted).
// - Short-hand (standard, really) string initialization.
let strings = characters.map { character in
return String(character)
}
// - Implicit return since using single expression in the closure (`return` keyword omitted).
let strings = characters.map { character in String(character) }
// - Shorthand argument names (`in` keyword and argument names omitted).
let strings = characters.map { String($0) }
// - Initializer expression syntax used (curly braces omitted, argument implicitly passed to the initializer).
let strings = characters.map(String.init(_:))
// - Initializer expression argument names inferred from context.
let strings = characters.map(String.init)
Ответ 3
В Swift 3.0
Используйте components(separatedBy:)
для строки, чем componentsSeparatedByString
.
Пример кода обмена
let tempString = "1.Wash your hands\n2.Check you phone\n3.Click home button".components(separatedBy: "\n")
print(tempString)
Ответ 4
"Я знаю, что он не работает"
Хорошо, для меня это так. В Swift REPL:
1> import Foundation
2> "a b c".componentsSeparatedByString(" ")
$R6: String[] = size=3 {
[0] = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000100407980
_countAndFlags = -4611686018427387903
_owner = Some {
Some = @"a"
}
}
}
[1] = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000100408e50 -> 0x00007fff7cde0062 (void *)0x001b00007fff7cdd
_countAndFlags = -4611686018427387903
_owner = Some {
Some = @"b"
}
}
}
[2] = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000100408dd0
_countAndFlags = -4611686018427387903
_owner = Some {
Some = @"c"
}
}
}
}