I have a string that I got from a text file.
Text file:
Line 1
Line 2
Line 3
...
I want to convert it to an array, one array element p
In Swift 2, the top-level split
function is now a method on CollectionType
(which each of String
s "character views" conforms to). There are two versions of the method, you want the one that takes a closure as a predicate to indicate whether a given element should be treated as a separator.
You can get the character collection from the string as a collection of UTF16 characters using string.utf16
, making them compatible with the NSCharacterSet
APIs. This way, we can easily check inside the closure whether a given character in the string is a member of the newline character set.
It's worth noting that split(_:)
will return a SubSequence
of characters (basically a Slice
), so it needs transforming back into an array of Strings which is generally more useful. I've done this below using flatMap(String.init)
- the UTF16View
initialiser on String
is failable, so using flatMap
will ignore any nil
values that might be returned, ensuring you get an array of non-optional strings back.
So for a nice Swift-like way of doing this:
let str = "Line 1\nLine 2\r\nLine 3\n"
let newlineChars = NSCharacterSet.newlineCharacterSet()
let lines = str.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init)
// lines = ["Line 1", "Line 2", "Line 3"]
What makes this nice is that the split
method has a parameter allowEmptySubsequences
, which ensures you don't receive any empty character sequences in the result. This is false
by default, so you don't actually need to specify it at all.
If you want to avoid NSCharacterSet
altogether, you can just as easily split the collection of unicode compliant Character
s.
let lines = str.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init)
Swift is able to treat "\r\n"
as a single extended grapheme cluster, using it as a single Character
for the comparison instead of creating a String
. Also note that the initialiser for creating a string from a Character
is non failable, so we can just use map
.