添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
无邪的铁板烧  ·  Android ...·  4 月前    · 

在上一篇 文章中, 我介绍了 Swift 中的高阶函数,解释了这种函数是什么以及如何创建自己的函数。在这篇文章中,我将专注于 Swift 中捆绑的一些特定的高阶函数,我也会在下一篇文章中继续这样做。

今天我将重点介绍三个高阶函数。人们可以看出他们属于同一个家庭;然而,它们有一定的差异,每个都用于特定的目的和用例。这些都是 map compactMap flatMap 高阶函数。

强调 所有 map 函数都适用于集合 是非常重要和必要的;数组、字典和集合。然而,看到它们更频繁地与数组一起使用是很常见的,因为这是编码时最常用的集合类型。

映射高阶函数

map 高阶函数的目的是*遍历集合的所有元素,对每个元素进行操作,并返回一个带有结果的新集合。*换句话说,它获取一个集合作为输入,用它做一些事情,然后返回另一个集合。

此外, map 与任何其他高阶函数一样,函数可以帮助我们编写更短、更清晰的代码。发生这种情况是因为使用一行代码,我们可以用自定义实现替换一堆行,这些实现将对集合执行完全相同的操作。

以下示例将有助于清除所有这些。要查看所有操作,只需在 Xcode 中打开一个操场并使用您将在此过程中遇到的代码。

让我们从以下数组开始;它包含十个随机国家的名称:

let  countries  =  ["France",  "Germany",  "United States of America",  "United Kingdom",  "Australia",  "Greece",  "Italy",  "Spain",  "Canada",  "Egypt"]

为了这个例子,假设我们想提出一个新数组,其中每个项目将显示每个国家/地区名称的长度。让我们首先使用自定义实现,而不使用任何高阶函数:

var  namesLength  =  [Int]()
for  i  in  0..<countries.count  {
    let  totalChars  =  countries[i].count
    namesLength(totalChars)

第一步是初始化一个新数组(namesLength上面调用)。然后,在一个for-in循环中,我们获取每个名称字符串的长度,然后将其附加到新数组中。

现在让我们使用map高阶函数。为此,我们使用原始集合中的点语法访问它。它接受一个方法或一个闭包作为参数,在它的主体内部实现了自定义逻辑。在这里,我们将返回每个国家/地区名称的长度。最常见的方法是使用闭包,并按照 Xcode 的自动建议自动附加闭包的主体:

namesLength  =  countries.map  {  (country)  ->  Int  in
    return  country.count

闭包中的参数值表示countries数组中的每个国家/地区名称。还有一个返回值;在这个例子中,我们想要返回一个整数,显示每个国家名称的长度。

上面的实现肯定比自定义的要短,但是通过省略返回类型和return闭包体内的关键字,它可以变得更短:

namesLength  =  countries.map  {  country in
    country.count

即使不再显式指定返回类型,它也会根据闭包主体中的任何计算或操作产生的返回值自动推断。

上面可以变得更短更简单,这次我们将省略参数值。相反,我们将使用速记参数

namesLength  =  countries.map  {
    $0.count

当然,我们可以只在一行中写上上面的内容:

namesLength  =  countries.map  {  $0.count  }

我们不仅用一行替换了原来的五行代码,而且与最初的实现相比,上面的语句要简洁得多。map函数创建一个新数组,在每个位置附加相应国家/地区名称的长度,同时countries在幕后遍历数组中的所有名称。

以上所有代码片段都是等价的,它们返回以下数组:

[6,  7,  24,  14,  9,  6,  5,  5,  6,  9]

这是使用该map函数的另一个示例。它将所有国家/地区名称转换为大写,并将它们附加到一个新数组中:

let  uppercasedCountries  =  countries.map  {  $0.uppercased()  }
print(uppercasedCountries)

打印的数组如下:

["FRANCE",  "GERMANY",  "UNITED STATES OF AMERICA",  "UNITED KINGDOM",  "AUSTRALIA",  "GREECE",  "ITALY",  "SPAIN",  "CANADA",  "EGYPT"]

map使用字典时,高阶函数也非常有用。它最大的优点之一是它可以很容易地分离键和值,从而获得包含一个或另一个的两个不同的数组。

让我们以下面的字典为例,它包含前面例子中的国家和它们所属的大陆:

var  countriesAndContinents  =  ["France":  "Europe",  "Germany":  "Europe",                              "United States of America":  "America",                              "United Kingdom":  "Europe",                              "Australia":  "Australia",                              "Greece":  "Europe",  "Italy":  "Europe",                              "Spain":  "Europe",  "Canada":  "America",                              "Egypt":  "Africa"]

以下两行返回两个不同数组中的键和值:

let  keys  =  countriesAndContinents.map  {  $0.key  }
let  values  =  countriesAndContinents.map  {  $0.value  }

但是map的用处并不止于此;在修改键或值后,我们可以轻松地获得一个新字典,并使用map.

为了展示这一点,假设我们想创建一个新字典,其中包含所有大写的值(本例中的大洲)。显然,以下内容是不正确的,因为它返回一个仅包含所有值的数组:

let  results  =  countriesAndContinents.map  {  $0.value.uppercased()  }

实际工作的技巧如下:

let  results  =  countriesAndContinents.map  {  ($0.key,  $0.value.uppercased())  }

看到从的闭包返回了一个元组map。第一个值是每个键,第二个是每个大写的值。results数组是一个元组数组,它​​是有目的的。我们可以通过将它作为参数提供给 Dictionary 类型的特定初始化器来使用它,因此最终得到一个新字典:

let  updatedCountriesAndContinents  =  Dictionary(uniqueKeysWithValues:  results)

打印updatedCountriesAndContinents将显示:

["United States of America":  "AMERICA",  "Spain":  "EUROPE",  "Canada":  "AMERICA",  "Egypt":  "AFRICA",  "Italy":  "EUROPE",  "United Kingdom":  "EUROPE",  "Germany":  "EUROPE",  "Australia":  "AUSTRALIA",  "Greece":  "EUROPE",  "France":  "EUROPE"]

compactMap 高阶函数

如果您知道如何map工作,那么您可以以类似的方式使用这两者compactMap以及flatMap您接下来将阅读的函数。

compactMap完全一样,map但有一个很大的不同;如果它们存在于原始集合中,它会忽略任何 nil 值

让我们countries再次以数组为例,只是这次 nil 值替换了一些实际的国家/地区名称:

let  countriesWithNil  =  ["France",  nil,  "United States of America",  nil,  "Australia",  "Greece",  nil,  "Spain",  nil,  "Egypt"]

为简单起见,让我们再次假设我们希望国家名称大写。使用map,我们需要有选择地解开map的参数:

let  uppercased  =  countriesWithNil.map  {  $0?.uppercased()  }

结果数组将包含以下可选值和 nil 值:

[Optional("FRANCE"),  nil,  Optional("UNITED STATES OF AMERICA"),  nil,  Optional("AUSTRALIA"),  Optional("GREECE"),  nil,  Optional("SPAIN"),  nil,  Optional("EGYPT")]

这有时可能适合您,但如果您想获得原始数组中具有实际名称的国家/地区的结果,那么compactMap您真正需要使用的是:

let  uppercased  =  countriesWithNil.compactMap  {  $0?.uppercased()  }

这次生成的数组不包含任何选项,并且省略了 nil 值:

["FRANCE",  "UNITED STATES OF AMERICA",  "AUSTRALIA",  "GREECE",  "SPAIN",  "EGYPT"]

知道现在compactMap做了什么,使用它而不是map当你想摆脱 nil 值时,或者只是在原始集合中忽略它们。除此之外,有关该map功能的所有其他讨论也适用于此。

flatMap 高阶函数

当您需要*从彼此包含的其他集合中获取单个集合时,*此高阶函数非常方便。为了澄清这一点,假设以下数组保持一个城市在早上和下午的平均温度(以摄氏度为单位):

let  temps  =  [15,  18]

现在假设我们有七个类似上面的数组到另一个数组中,匹配一周中的 7 天:

let  weekTemps  =  [[15,  18],  [17.5,  16],  [13.4,  14.1],  [14.4,  15.2],  [15,  15.8],  [16.8,  17.9],  [16,  18.2]]

现在,如果我们想计算整周的平均温度怎么办?如果我们可以将所有温度都存在于单个阵列中,那将非常方便。

这就是flatMap它的作用;它将嵌套集合中的值合并为一个单一的集合。实现这一目标所需的一切如下:

let  allTemps  =  weekTemps.flatMap  {  $0  }

所有温度现在都存在于一个数组中:

[15.0,  18.0,  17.5,  16.0,  13.4,  14.1,  14.4,  15.2,  15.0,  15.8,  16.8,  17.9,  16.0,  18.2]

上述转换使得处理这些值并使用它们做一些事情变得更加容易。

在上一篇对高阶函数的初步介绍之后,这里我简要介绍了如何使用 Swift 中提供的一些常见和相似的高阶函数,解释它们的用途、工作原理以及它们如何帮助编写更好的代码. 他们中的更多人将来到下一个帖子,所以不要错过它。感谢您的阅读时间!

  • 底层相关的面试文章(github.com/iOS-Mayday/…
  • 简历指导和常见算法(github.com/iOS-Mayday/…
  • 快手电商无线团队
    私信