使用闭包

使用闭包自定义排序

当你开始深入研究集合 (包括数组,字典,集合set)时,闭包就派上了用场。之前,我们使用数组的sorted()方法对数组进行排序。现在我们可以通过闭包,自定义排序。

调用sorted()来获得数组排序后的版本:
let names = ["ZZZZZZ", "BB", "A", "CCCC", "EEEEE"]
names.sorted()
// ["A", "BB", "CCCC", "EEEEE", "ZZZZZZ"]
通过自定义闭包,可以更改数组的排序细节。定义一个尾随闭包,如下所示:
names.sorted {
  $0.count > $1.count
}
// ["ZZZZZZ", "EEEEE", "CCCC", "BB", "A"]

现在,数组按字符串的长度排序,字符串的长度优先

使用闭包遍历集合

在Swift中,集合实现了一些非常方便的特性,这些特性通常与函数式编程相关联,这些特性以函数的形式出现,可以将这些功能应用到集合上,以对其执行操作。

转换元素

对集合中的元素进行循环,并执行操作:

let values = [1, 2, 3, 4, 5, 6]
values.forEach {
    print("\($0): \($0*$0)")
}

这个循环遍历集合中每个元素并打印值和值的平方

过滤元素

var prices = [1.5, 10, 4.99, 2.30, 8.19]
let largePrices = prices.filter {
     return $0 > 5
 } 

创建一个数组,表示商店中商品的价格。过滤大于$5的价格,你可以使用filter函数。这个函数看起来是这样的:

func filter(_ isIncluded: (Element) -> Bool) -> [Element]

这意味着filter只接受一个参数,它是一个闭包(或函数),它接受一个元素并返回一个Bool。然后,filter函数返回一个元素数组。在此上下文中,元素指的是数组中项目的类型。在上面的例子中,元素是Double类型

是否应该保留该值,这取决于闭包是返回true或false。从filter返回的数组将包含闭包返回true的所有元素。

在例子中,largeprice将包含:(10, 8.19)

注意:从filter(以及所有这些函数)返回的数组是一个新数组。原数组根本没有修改。

想象一下,你正在进行一场促销活动,想要把所有的商品都降价到原来的90%。有一个很方便的函数,叫做map,它可以做到这一点:

let salePrices = prices.map {
 return $0 * 0.9
}

map函数接受一个闭包,在数组中的每个条目都会执行它,并返回一个包含所有执行结果的新数组,并保持该顺序。在这种情况下,
salePrices将包含:[1.35, 9, 4.491, 2.07, 7.371]

map函数可以用来改变类型

let userInput = ["0", "11", "haha", "42"]
let numbers1 = userInput.map {
    Int($0)
 } 

用户输入字符串并将它们转换成整数数组。但是它们需要是可选的,因为从string到Int的转换可能会失败。

如果你想要过滤掉无效的(丢失的)值,可以使用flatMap():

let numbers2 = userInput.flatMap {Int($0)} 

flatMap几乎和map一样,只是它创建了一个Int数组,并抛出了缺失值。

另一个方便的函数叫做reduce。这个函数取一个起始值和一个闭包。闭包取两个值:当前值和数组中的元素。闭包的返回值作为当前值参数传入闭包。

这可以用于价格数组来计算总数,比如:

let sum = prices.reduce(0) {
 return $0 + $1
}

初始值为0。然后,闭包计算当前值的和加上当前迭代的值。这样就计算了数组中所有值的总和。在这种情况下,sum将是:
26.98

现在你已经知道了filter、map和reduce,希望能够清楚地了解这些函数的强大程度,特别是闭包的语法。在几行代码中,你已经可以从集合中计算相当复杂的值。

这些函数也可以用于字典。想象一下,你在你的仓库里用一个字典来表示你的股票,用这个价格映射到商品的数量上。你可以用它来计算你的股票的总价值:

let stock = [1.5: 5, 10: 2, 4.99: 20, 2.30: 5, 8.19: 30]
let stockSum = stock.reduce(0) {
   return $0 + $1.key * Double($1.value)
}

在本例中,reduce函数的第二个参数是一个tuple,它包含来自字典元素的键和值。计算值需要类型转换。

结果是:384.5

还有另一种形式的reduce,当你需要将集合变为数组或字典时,它是有用的。它叫做reduce(into:_:)。你可以这样使用:

let farmAnimals = ["🐎": 5, "🐄": 10 ,"🐑": 50 ,"🐶": 1]

let allAnimals = farmAnimals.reduce(into: []) { 
(result, this: (key: String, value: Int)) in

  for _ in 0 ..< this.value {
    result.append(this.key)
  }

 } 

它与其他版本的执行完全相同,只是不从闭包返回什么。相反,每个迭代都给你一个可变的值来处理。这样,在这个示例中只有一个数组被创建并添加元素。。

还有一些不同的功能,在你需要切割的时候会很有用。

dropFirst

let removeFirst = prices.dropFirst()
let removeFirstTwo = prices.dropFirst(2)

dropFirst函数接受一个默认值为1的参数,并返回一个数组,其中包含从前面删除的元素。在这种情况下,结果如下:

removeFirst = [10, 4.99, 2.30, 8.19]
removeFirstTwo = [4.99, 2.30, 8.19]

就像dropFirst一样,也存在从数组末尾移除元素的dropLast。是这样的:

dropLast

let removeLast = prices.dropLast()
let removeLastTwo = prices.dropLast(2)

这些结果如你所料,如下:

removeLast = [1.5, 10, 4.99, 2.30]
removeLastTwo = [1.5, 10, 4.99]

可以获取数组的第一个或最后一个元素,如下所示:

let firstTwo = prices.prefix(2)
let lastTwo = prices.suffix(2)

这里,prefix返回数组前面的元素,suffix返回 数组后面的元素。该函数的结果为:

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

推荐阅读更多精彩内容

  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,092评论 0 21
  • 简介:Groovy中的闭包就是去掉冗长无用代码的短小的匿名方法,闭包从函数式编程的Lambda表达式(指定了一个函...
    one_mighty阅读 447评论 0 0
  • 智者说,态度决定你成功的高度和速度。赞同。追加一句,态度要配的上你的梦想,否则,屁也不是。 1你梦想成为服装设计师...
    风习习阅读 154评论 0 0
  • 文|秋思说财 未经允许 不得转载 在《基金定投你真的了解吗?为什么它比一次性投资好?》一文中,基金定投是在牛市、熊...
    秋思说阅读 939评论 2 6
  • 龙生九子,九子各不同,及至今日,不依赖拼音,我也认不全它们的名字。 在大理,这个黄龙玉馆给我留下了深刻印象,是因为...
    丹菡阅读 757评论 2 5