Reputation: 1664
Looking for an (elegant) solution for splitting a string and keeping the separator as item(s) in the array
example 1:
"hello world"
["hello", " ", "world"]
example 2:
" hello world"
[" ", "hello", " ", "world"]
thx.
Upvotes: 5
Views: 2281
Reputation: 320
let sample = "a\nb\n\nc\n\n\nd\n\nddddd\n \n \n \n\n"
let sep = "\n"
let result = sample.components(separatedBy: sep).flatMap {
$0 == "" ? [sep] : [$0, sep]
}.dropLast()
debugPrint(result) // ArraySlice(["a", "\n", "b", "\n", "\n", "c", "\n", "\n", "\n", "d", "\n", "\n", "ddddd", "\n", " ", "\n", " ", "\n", " ", "\n", "\n"])
Upvotes: 0
Reputation: 285069
Just for fun, the Swift Algorithms package contains an algorithm called Intersperse
After adding the package and
import Algorithms
you can write
let string = "hello world"
let separator = " "
let result = Array(string
.components(separatedBy: separator)
.interspersed(with: separator))
print(result)
Your second example is barely correct, the result of splitting " hello world"
by space is
["", "hello", "world"]
Upvotes: 0
Reputation: 53112
For people who have a condition for their split, for example: splitting a camelCaseString based on uppercase condition:
extension Sequence {
func splitIncludeDelimiter(whereSeparator shouldDelimit: (Element) throws -> Bool) rethrows -> [[Element]] {
try self.reduce([[]]) { group, next in
var group = group
if try shouldDelimit(next) {
group.append([next])
} else {
group[group.lastIdx].append(next)
}
return group
}
}
}
For example:
"iAmCamelCase".splitIncludeDelimiter(whereSeparator: \.isUppercase)
=>
["i", "Am", "Camel", "Case"]
(If you want the imp of isUppercase)
extension CharacterSet {
static let uppercaseLetters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
}
extension Unicode.Scalar {
var isUppercase: Bool {
CharacterSet.uppercaseLetters.contains(self)
}
}
Upvotes: 1
Reputation: 271030
Suppose you are splitting the string by a separator called separator
, you can do the following:
let result = yourString.components(separatedBy: separator) // first split
.flatMap { [$0, separator] } // add the separator after each split
.dropLast() // remove the last separator added
.filter { $0 != "" } // remove empty strings
For example:
let result = " Hello World ".components(separatedBy: " ").flatMap { [$0, " "] }.dropLast().filter { $0 != "" }
print(result) // [" ", "Hello", " ", "World", " "]
Upvotes: 11