Functional Programming in Swift
Extracting a list of names from a list of Person(s)
Section titled “Extracting a list of names from a list of Person(s)”Given a Person struct
struct Person { let name: String let birthYear: Int?}and an Array of Person(s)
let persons = [ Person(name: "Walter White", birthYear: 1959), Person(name: "Jesse Pinkman", birthYear: 1984), Person(name: "Skyler White", birthYear: 1970), Person(name: "Saul Goodman", birthYear: nil)]we can retrieve an array of String containing the name property of each Person.
let names = persons.map { $0.name }// ["Walter White", "Jesse Pinkman", "Skyler White", "Saul Goodman"]Traversing
Section titled “Traversing”let numbers = [3, 1, 4, 1, 5]// non-functionalfor (index, element) in numbers.enumerate() { print(index, element)}
// functionalnumbers.enumerate().map { (index, element) in print((index, element))}Filtering
Section titled “Filtering”Create a stream by selecting the elements from a stream that pass a certain condition is called filtering
var newReleases = [ [ "id": 70111470, "title": "Die Hard", "boxart": "http://cdn-0.nflximg.com/images/2891/DieHard.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 4.0, "bookmark": [] ], [ "id": 654356453, "title": "Bad Boys", "boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [[ "id": 432534, "time": 65876586 ]] ], [ "id": 65432445, "title": "The Chamber", "boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 4.0, "bookmark": [] ], [ "id": 675465, "title": "Fracture", "boxart": "http://cdn-0.nflximg.com/images/2891/Fracture.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [[ "id": 432534, "time": 65876586 ]] ]]
var videos1 = [[String: AnyObject]]()/** * Filtering using map */newReleases.map { e in if e["rating"] as! Float == 5.0 { videos1.append(["id": e["id"] as! Int, "title": e["title"] as! String]) }}
print(videos1)
var videos2 = [[String: AnyObject]]()/** * Filtering using filter and chaining */newReleases .filter{ e in e["rating"] as! Float == 5.0 } .map { e in videos2.append(["id": e["id"] as! Int, "title": e["title"] as! String])}
print(videos2)Using Filter with Structs
Section titled “Using Filter with Structs”Frequently you may want to filter structures and other complex data types. Searching an array of structs for entries that contain a particular value is a very common task, and easily achieved in Swift using functional programming features. What’s more, the code is extremely succinct.
struct Painter { enum Type { case Impressionist, Expressionist, Surrealist, Abstract, Pop } var firstName: String var lastName: String var type: Type}
let painters = [ Painter(firstName: "Claude", lastName: "Monet", type: .Impressionist), Painter(firstName: "Edgar", lastName: "Degas", type: .Impressionist), Painter(firstName: "Egon", lastName: "Schiele", type: .Expressionist), Painter(firstName: "George", lastName: "Grosz", type: .Expressionist), Painter(firstName: "Mark", lastName: "Rothko", type: .Abstract), Painter(firstName: "Jackson", lastName: "Pollock", type: .Abstract), Painter(firstName: "Pablo", lastName: "Picasso", type: .Surrealist), Painter(firstName: "Andy", lastName: "Warhol", type: .Pop)]
// list the expressionistsdump(painters.filter({$0.type == .Expressionist}))
// count the expressionistsdump(painters.filter({$0.type == .Expressionist}).count)// prints "2"
// combine filter and map for more complex operations, for example listing all// non-impressionist and non-expressionists by surnamedump(painters.filter({$0.type != .Impressionist && $0.type != .Expressionist}) .map({$0.lastName}).joinWithSeparator(", "))// prints "Rothko, Pollock, Picasso, Warhol"Projecting
Section titled “Projecting”Applying a function to a collection/stream and creating a new collection/stream is called a projection.
/// Projectionvar newReleases = [ [ "id": 70111470, "title": "Die Hard", "boxart": "http://cdn-0.nflximg.com/images/2891/DieHard.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": [4.0], "bookmark": [] ], [ "id": 654356453, "title": "Bad Boys", "boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": [5.0], "bookmark": [[ "id": 432534, "time": 65876586 ]] ], [ "id": 65432445, "title": "The Chamber", "boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": [4.0], "bookmark": [] ], [ "id": 675465, "title": "Fracture", "boxart": "http://cdn-0.nflximg.com/images/2891/Fracture.jpg", "uri": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": [5.0], "bookmark": [[ "id": 432534, "time": 65876586 ]] ]]
var videoAndTitlePairs = [[String: AnyObject]]()newReleases.map { e in videoAndTitlePairs.append(["id": e["id"] as! Int, "title": e["title"] as! String])}
print(videoAndTitlePairs)