Optional 中的 map 和 flatMap

最近在国外的网上看到一篇介绍 Optional 中 map 和 flatMap 的文章(需要翻墙),觉得受益良多,给大家分享一下。如果你不知道 Swift 中的 map 和 flatMap,可以看看唐巧的Swift 烧脑体操(四) - map 和 flatMap,这篇文章也有介绍 Optional 中的 map 和 flatMap。

我们先看一个例子

var value: Int? = 2
var newValue = value.map { $0 * 2 }
// newValue is now Optional(4)

value = nil
newValue = value.map { $0 * 2 }
// newValue is now nil

在 Optional 中,map 方法不会关心自己是否是.None,可以直接进行修改,而如果不用 map,那么可能要先保证自己不是.None才能进行修改,比如我们对上面的例子做一个修改

if value != nil {
  newValue = value! * 2
}

如果我们要对 value 进行运算,那么首先要保证 value 有值才能进行,相比于用 map 的方式,很明显要臃肿。
map 方法提供了一种无需对 Optional 进行解包就可以直接修改的方式,很便捷。
我们再来看看 flatMap

value = 10
newValue = value.flatMap{ $0 / 5 }
// newValue is now Optional(2)

咋一看,好像没啥区别,那么换一种写法

newValue = value.map({ (i) -> Int in
    i / 5
})

newValue = value.flatMap({ (i) -> Int? in
    if i < 5 {
        return nil
    }
    return i / 5
})

此时我们可以看到,map 和 flatMap 在闭包中的返回值是不同的,map 的返回值不能是 nil,但是 flatMap 可以。我们在具体使用时,要根据 Closure 中的返回值类型来选择不同的方法。

再来几个例子:

String 字面量值

// Without map:
func ageToString(age: Int?) -> String {
    return age == nil ? "Unknown age" : "She is \(age!) years old"
}

// With map:
func ageToString(age: Int?) -> String {
    return age.map { "She is \($0) years old" } ?? "Unknown age"
}

本地化 String

// Without map:
let label = UILabel()
func updateLabel(value: String?) {
  if let value = value {
    label.text = String.localizedStringWithFormat(
      NSLocalizedString("value %@", comment: ""), value)
  } else {
    label.text = nil
  }
}

// With map:
let label = UILabel()
func updateLabel(value: String?) {
  label.text = value.map { 
    String.localizedStringWithFormat(NSLocalizedString("value %@", comment: ""), $0) 
  }
}

根据某一条件在数组中找到对应元素

struct Item {
    let identifier: String
}
let items: [Item]

// Without map:
func find(identifier: String) -> Item? {
    if let index = items.indexOf({$0.identifier == identifier}) {
        return items[index]
    }
    return nil
}

// With map:
func find(identifier: String) -> Item? {
    return items.indexOf({$0.identifier == identifier}).map({items[$0]})
}

解析 Json 字典

struct Person {
    let firstName: String
    let lastName: String

    init?(json: [String: AnyObject]) {
        if let firstName = json["firstName"] as? String, let lastName = json["lastName"] as? String {
            self.firstName = firstName
            self.lastName = lastName
            return
        }
        return nil
    }
}

// Without map:
func createPerson(json: [String: AnyObject]) -> Person? {
    if let personJson = json["person"] as? [String: AnyObject] {
        return Person(json: personJson)
    }
    return nil
}

// With map:
func createPerson(json: [String: AnyObject]) -> Person? {
    return (json["person"] as? [String: AnyObject]).flatMap(Person.init)
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 一、数组中的 map 和 flatMap 数组中的 map 对数组元素进行某种规则的转换,例如: 二、 flatM...
    kmplayer阅读 4,006评论 0 6
  • 对各种值为"空"的情况处理不当,几乎是所有Bug的来源。 在我们的例子里,尽管tmp的值是nil,但调用tmp的r...
    AKyS佐毅阅读 10,510评论 1 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • map 和 flatMap 是 Swift 中两个常用的函数,它们体现了 Swift 中很多的特性。对于简单的使用...
    SwiftCafe阅读 1,567评论 5 16
  • 震荡了一天, 看强不强,看弱不弱。3100的支撑效应仍旧明显。有没有国家队进场我并不知道,我只知道如果延续这种走...
    光生丨寒夜阅读 233评论 0 0