10 awesome lines of Swift code

  • 2020-05-15 02:15:14
  • OfStack

A few years ago, an article describing "10 Scala functional one-line code" was very popular, and other language versions immediately followed, such as the Haskell version, Ruby version, Groovy version, Clojure version, Python version, C# version, F# version, CoffeeScript version, etc.

We don't know how many people are really impressed with this one-line code, but I think it will inspire you to learn more about functional programming.

1 times each element in the array times 2

Very simple, especially if you use map.

(1...1024).map{$0 * 2}

The sum of the elements in the 2 array

Although reduce and the plus operator are used here, with the help of the fact that the plus operator is a function, the solution is obvious and we can see a more creative use of reduce.

(1...1024).reduce(0,combine: +)

Verify the existence of the specified word in the string

Let's use filter to verify that tweet contains one of the selected keywords:


let words = ["Swift","iOS","cocoa","OSX","tvOS"]
let tweet = "This is an example tweet larking about Swift"
let valid = !words.filter({tweet.containsString($0)}).isEmpty
valid //true

Update: @oisdk suggests some better options:

words.contains(tweet.containsString)

A more concise way, and this one:


tweet.characters
.split(" ")
.lazy
.map(String.init)
.contains(Set(words).contains)

4 read files

Like other languages 1, it is not possible to simply read files into an array with built-in ease, but we can combine split and map to create a short code that does not require an for loop:


let path = NSBundle.mainBundle().pathForResource("test", ofType: "txt")
let lines = try? String(contentsOfFile: path!).characters.split{$0 == "\n"}.map(String.init)
if let lines=lines {
  lines[0] // O! for a Muse of fire, that would ascend
  lines[1] // The brightest heaven of invention!
  lines[2] // A kingdom for a stage, princes to act
  lines[3] // And monarchs to behold the swelling scene.
}

map and the last step of the string constructor converts our array characters to strings.

Happy birthday to you!

This will display the happy birthday song to the console, via map as well as the simple use of the range and 3 meta operators.


let name = "uraimo"
(1...4).forEach{print("Happy Birthday " + (($0 == 3) ? "dear \(name)":"to You"))}

6 filters the Numbers in the array

In this case, we need to partition 1 sequence using the provided filter function. Many languages have map, flatMap, reduce, filter, and so on in common use, as well as partitionBy functions that do just that. Swift, as you know, doesn't have anything like that (NSPredicate provides a filter NSArray function that we don't need here).

Therefore, we can use the partitionBy function to extend SequenceType to solve this problem. We will use the partitionBy function to partition the integer array:


extension SequenceType{
    typealias Element = Self.Generator.Element
    func partitionBy(fu: (Element)->Bool)->([Element],[Element]){
    var first=[Element]()
    var second=[Element]()
    for el in self {
    if fu(el) {
    first.append(el)
  }else{
    second.append(el)
    }
  }
    return (first,second)
  }
}
let part = [82, 58, 76, 49, 88, 90].partitionBy{$0 < 60}
part // ([58, 49], [82, 76, 88, 90])

Not really a single line of code. So, can we use filters to improve it?


extension SequenceType{
  func anotherPartitionBy(fu: (Self.Generator.Element)->Bool)->([Self.Generator.Element],[Self.Generator.Element]){
    return (self.filter(fu),self.filter({!fu($0)}))
  }
}
let part2 = [82, 58, 76, 49, 88, 90].anotherPartitionBy{$0 < 60}
part2 // ([58, 49], [82, 76, 88, 90])

A little better by 1, but it iterates through the sequence twice, and trying to turn it into a single line of code to remove closures would result in too many duplicates (filtering functions and arrays are used in both places).

Do we use a single data stream to build something that converts the initial sequence into a partition tuple? Yes, we can use reduce.


var part3 = [82, 58, 76, 49, 88, 90].reduce( ([],[]), combine: {
  (a:([Int],[Int]),n:Int) -> ([Int],[Int]) in
  (n<60) ? (a.0+[n],a.1) : (a.0,a.1+[n])
})
part3 // ([58, 49], [82, 76, 88, 90])

Here we build a result tuple consisting of two partitions, one element at a time, testing each element in the initial sequence with a filter function, and appending that element to the first or second partition array based on the filter result.

You end up with a true single line of code, but note the fact that the partitioned array is built by apportion, which actually makes it slower than the previous two implementations.

7 get and parse the XML Web service

Some of the above languages don't rely on external libraries and provide multiple options to handle XML by default (for example, Scala awkwardly but "locally" supports XML parsing into objects), but Foundation only provides SAX parser NSXMLParser, and as you might have guessed, we don't plan to use it.

There are several alternative open source libraries that we can use in this situation, some of which are written in C or Objective-C, others are pure Swift.

This time, we plan to use AEXML pure Swift:


let xmlDoc = try? AEXMLDocument(xmlData: NSData(contentsOfURL: NSURL(string:"https://www.ibiblio.org/xml/examples/shakespeare/hen_v.xml")!)!)
if let xmlDoc=xmlDoc {
  var prologue = xmlDoc.root.children[6]["PROLOGUE"]["SPEECH"]
  prologue.children[1].stringValue // Now all the youth of England are on fire,
  prologue.children[2].stringValue // And silken dalliance in the wardrobe lies:
  prologue.children[3].stringValue // Now thrive the armourers, and honour's thought
  prologue.children[4].stringValue // Reigns solely in the breast of every man:
  prologue.children[5].stringValue // They sell the pasture now to buy the horse,
}

8 looks for the minimum (or maximum) value in the array

We have various methods to find the minimum and maximum values in the sequence, among which are the minElement and maxElement functions:


//Find the minimum of an array of Ints
[10,-22,753,55,137,-1,-279,1034,77].sort().first
[10,-22,753,55,137,-1,-279,1034,77].reduce(Int.max, combine: min)
[10,-22,753,55,137,-1,-279,1034,77].minElement()
//Find the maximum of an array of Ints
[10,-22,753,55,137,-1,-279,1034,77].sort().last
[10,-22,753,55,137,-1,-279,1034,77].reduce(Int.min, combine: max)
[10,-22,753,55,137,-1,-279,1034,77].maxElement()

9 parallel processing

Some languages allow array pairs to be enabled in a simple and transparent way, such as map and flatMap's parallel processing, to speed up the execution of sequential and independent operations.

This function is not available in the Swift, but can use GCD construction: http: / / moreindirection blogspot. it / 2015/07 / gcd - and - parallel - collections - in - swift. html

Eratosthenes sieve

The Eratosthenes sieve is used to find all primes up to a given upper limit, n.

Starting with a sequence of all integers smaller than n, the algorithm deletes multiples of all integers until only primes are left. And to speed up the execution, we don't actually need to check the multiples of each integer, we just stop at the square root of n.

The first execution based on this 1 definition might look like this:


var n = 50
var primes = Set(2...n)
(2...Int(sqrt(Double(n)))).forEach{primes.subtractInPlace((2*$0).stride(through:n, by:$0))}
primes.sort()

We use an external range to iterate over the integers we are checking, and for each integer we use stride(through:Int: by:Int) to calculate a sequence of multiples of the number. Those sequences are then subtracted from Set, which is initialized with all integers from 2 to n.

But as you can see, in order to actually remove multiples, we use an external variable Set, which leads to collateral damage.

To eliminate collateral damage, as we should normally do, we first evaluate all sequences, flatMap them with multiples of a single 1 array, and remove the integers from the original Set.


tweet.characters
.split(" ")
.lazy
.map(String.init)
.contains(Set(words).contains)
0

Cleaner, use a good example from flatMap to generate flat nested arrays.

11 others: by deconstructing tuple exchange

Finally, not everyone knows that tuples, like other languages with tuple type 1, can be used to perform compact variable swapping:


tweet.characters
.split(" ")
.lazy
.map(String.init)
.contains(Set(words).contains)
1

Well, as expected, Swift and other languages 1 are expressive.

Do you have any other interesting one-line Swift code you'd like to share? 1 get up and have a chat!

10. Swift One Liners To Impress Your Friends


Related articles: