In Swift, Can You Split a String by Another String, Not Just a Character

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 Strings, 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



Leave a reply



Submit