In Swift, can you split a string by another string, not just a character?
import Foundation
let inputString = "This123Is123A123Test"
let splits = inputString.components(separatedBy: "123")
Split a string by an entire word, not just one character
You can use components(separatedBy:) method to get an array of string by separating a string with a string separator
var str = "another test= long test"
let strspl = "test="
let spl : [String] = str.components(separatedBy: strspl)
print(spl)
["another ", " long test"]
Split a String into an array in Swift?
The Swift way is to use the global split
function, like so:
var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}
var firstName: String = fullNameArr[0]
var lastName: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil
with Swift 2
In Swift 2 the use of split becomes a bit more complicated due to the introduction of the internal CharacterView type. This means that String no longer adopts the SequenceType or CollectionType protocols and you must instead use the .characters
property to access a CharacterView type representation of a String instance. (Note: CharacterView does adopt SequenceType and CollectionType protocols).
let fullName = "First Last"
let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init)
// or simply:
// let fullNameArr = fullName.characters.split{" "}.map(String.init)
fullNameArr[0] // First
fullNameArr[1] // Last
Split a String without removing the delimiter in Swift
This method works on CollectionTypes
, rather than String
s, but it should be easy enough to adapt:
extension CollectionType {
func splitAt(@noescape isSplit: Generator.Element throws -> Bool) rethrows -> [SubSequence] {
var p = startIndex
return try indices
.filter { i in try isSplit(self[i]) }
.map { i in
defer { p = i }
return self[p..<i]
} + [suffixFrom(p)]
}
}
extension CollectionType where Generator.Element : Equatable {
func splitAt(splitter: Generator.Element) -> [SubSequence] {
return splitAt { el in el == splitter }
}
}
You could use it like this:
let sentence = "Hello, my name is oisdk. This should split: but only at punctuation!"
let puncSet = Set("!.,:".characters)
sentence
.characters
.splitAt(puncSet.contains)
.map(String.init)
// ["Hello", ", my name is oisdk", ". This should split", ": but only at punctuation", "!"]
Or, this version, which uses a for-loop, and splits after the delimiter:
extension CollectionType {
func splitAt(@noescape isSplit: Generator.Element throws -> Bool) rethrows -> [SubSequence] {
var p = startIndex
var result: [SubSequence] = []
for i in indices where try isSplit(self[i]) {
result.append(self[p...i])
p = i.successor()
}
if p != endIndex { result.append(suffixFrom(p)) }
return result
}
}
extension CollectionType where Generator.Element : Equatable {
func splitAt(splitter: Generator.Element) -> [SubSequence] {
return splitAt { el in el == splitter }
}
}
let sentence = "Hello, my name is oisdk. This should split: but only at punctuation!"
let puncSet = Set("!.,:".characters)
sentence
.characters
.splitAt(puncSet.contains)
.map(String.init)
// ["Hello,", " my name is oisdk.", " This should split:", " but only at punctuation!"]
Or, if you wanted to get the most Swift features into one function (defer
, throws
, a Protocol extension, an evil flatMap
, guard
, and Optionals):
extension CollectionType {
func splitAt(@noescape isSplit: Generator.Element throws -> Bool) rethrows -> [SubSequence] {
var p = startIndex
var result: [SubSequence] = try indices.flatMap { i in
guard try isSplit(self[i]) else { return nil }
defer { p = i.successor() }
return self[p...i]
}
if p != endIndex { result.append(suffixFrom(p)) }
return result
}
}
Splitting a Swift String using a multi-Character String in Swift 2
Here's a rather simple-minded approach that makes it possible to use Swift split
on a single character:
extension String {
mutating func replace(target:String, with:String) {
while let r = self.rangeOfString(target) {
self.replaceRange(r, with: with)
}
}
func split(separator:String) -> Array<String> {
var s = self
s.replace(separator, with:"☞") // arbitrary improbable character :)
return s.characters.split("☞").map{String($0)}
}
}
var s = "the${cat${sat${on${the${mat"
let arr = s.split("${")
However, rangeOfString
is actually a Foundation method on NSString; if you don't import Foundation (or UIKit), that code won't compile. So in reality it's no improvement over just calling componentsSeparatedByString
. I don't actually understand your objection to it in the first place; Swift has holes exactly because it expects Foundation to be backing it up and filling those holes.
Splitting a string in swift using multiple delimiters
This isn't very efficient, but it should do the job:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String] {
let inds = ss.flatMap { s in
self.rangeOfString(s).map { r in [r.startIndex, r.endIndex] } ?? []
}
let ended = [startIndex] + inds + [endIndex]
let chunks = stride(from: 0, to: ended.count, by: 2)
let bounds = map(chunks) { i in (ended[i], ended[i+1]) }
return bounds
.map { (s, e) in self[s..<e] }
.filter { sl in !sl.isEmpty }
}
}
"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"])
// ["=subKey1=value&subkey2=value", "=subkey1=value&subkey2=value", "=subKey1=value&subkey3=value"]
Or, if you wanted it in dictionary form:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String:String] {
let maybeRanges = ss.map { s in self.rangeOfString(s) }
let inds = maybeRanges.flatMap { $0.map { r in [r.startIndex, r.endIndex] } ?? [] }
let ended = [startIndex] + inds + [endIndex]
let chunks = stride(from: 0, to: ended.count, by: 2)
let bounds = map(chunks) { i in (ended[i], ended[i+1]) }
let values = bounds
.map { (s, e) in self[s..<e] }
.filter { sl in !sl.isEmpty }
let keys = filter(zip(maybeRanges, ss)) { (r, _) in r != nil }
var result: [String:String] = [:]
for ((_, k), v) in zip(keys, values) { result[k] = v }
return result
}
}
"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"])
// ["KEY3": "=subKey1=value&subkey3=value", "KEY2": "=subkey1=value&subkey2=value", "KEY1": "=subKey1=value&subkey2=value"]
For Swift 2:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String] {
let unshifted = ss
.flatMap { s in rangeOfString(s) }
.flatMap { r in [r.startIndex, r.endIndex] }
let inds = [startIndex] + unshifted + [endIndex]
return inds.startIndex
.stride(to: inds.endIndex, by: 2)
.map { i in (inds[i], inds[i+1]) }
.flatMap { (s, e) in s == e ? nil : self[s..<e] }
}
}
Split string based on symbols $$ and && to access data in Swift
You can use the components method to split your string.
Step 1: Split it by the "$$" separator, which will give you an array of strings. An instance element in that array will look something like this "7460&&Presentation Name2".
Step 2: Split that array again, now by the "&&" separator, which gives you the ["7460", "Presentation Name2"] array.
Step 3: From that array, you need to extract the values and assign them to your arrays.
let yourString = "$$5955&&Presentation Name1 [CLONE]$$7460&&Presentation Name2 $$7473&&Presentation Name3$$7626&&Presentation Name4 [CLONE]$$7460&&Presentation Name5$$7123&&Presentation Name6"
var arrayPresentationNames: [String] = []
var arrayID: [String] = []
// Step 1 - Separate the string by the "$$"
yourString.components(separatedBy: "$$").forEach({ element in
// Step 2 - Separate the string by the "&&"
let splitedComponent = element.components(separatedBy: "&&")
if let presentationName = splitedComponent.first, !presentationName.isEmpty {
// Step 3/1 - Extract the presentation name
arrayPresentationNames.append(presentationName)
}
if splitedComponent.count > 1 {
// Step 3/2 - Extract the id
arrayID.append(splitedComponent[1])
}
})
print(arrayPresentationNames) // Prints your presentation names
print(arrayID) // Prints your id's
How to split a string in Swift
Try this:
var myString: String = "hello hi";
var myStringArr = myString.componentsSeparatedByString(" ")
Where myString
is the name of your string, and myStringArr
contains the components separated by the space.
Then you can get the components as:
var hello: String = myStringArr [0]
var hi: String = myStringArr [1]
Doc: componentsSeparatedByString
EDIT: For Swift 3, the above will be:
var myStringArr = myString.components(separatedBy: " ")
Doc: components(separatedBy:)
Related Topics
How to Implement Copy Constructor in Swift Subclass
Optional Field Type Doesn't Conform Protocol in Swift 3
Swift - Avaudioplayer, Sound Doesn't Play Correctly
How to Write a Function That Will Unwrap a Generic Property in Swift Assuming It Is an Optional Type
Division Not Working Properly in Swift
How to Install Xcode on an External Hard Drive Along with the iPhone Simulator.App
Exponentiation Operator in Swift
How to Run Xctest for a Swift Application from the Command Line
How to Include Assets/Resources in a Swift Package Manager Library
Swift 3.0 Iterate Over String.Index Range
Structs That Refer to Each Other in Swift 3
Best Practice for Swift Methods That Can Return or Error
Extending Collection with a Recursive Property/Method That Depends on the Element Type
What Are 'Get' and 'Set' in Swift