Swift 2.0 flatMap用法

时间:2016-03-02 09:59:47

标签: swift

当我找到以下几行时,我正在阅读由Apple(“Auto Layout Cookbook”)作为教程制作的文件中包含的代码:

web.example.com/dashboard

我重新编写文档并发现,如果我理解的话,当您需要将二维数组的内容转换为线性数组时,基本使用let recipies: [Recipe] = fileContents.flatMap { recipeData in // Fetch the recipe information. guard let title = recipeData["Title"], descriptionFileName = recipeData["Document"], identifierString = recipeData["Identifier"] else { assertionFailure("Unable to fetch recipe information.") return nil } // Convert the identifier string to an `Identifier` type. guard let identifier = CookbookStoryboardIdentifier(rawValue: identifierString) else { assertionFailure("Invalid recipe identifier: \(identifierString).") return nil } // Read the recipe description from the associated file. var description: String do { guard let descriptionURL = bundle.URLForResource(descriptionFileName, withExtension: nil) else { fatalError("Unable to determine recipe description URL from fileName: \(descriptionFileName).") } try description = NSString(contentsOfURL: descriptionURL, encoding: NSUTF8StringEncoding) as String } catch { fatalError("Unable to read recipe description from file") } return Recipe(title: title, identifier: identifier, description: description) }

如果是这样,我不明白:

  1. flatMap做了什么:我想它就像一个foreach;
  2. 为什么此代码会返回每个recipeData inRecipeRecipe);
  3. 为什么他们使用struct(什么是扁平?);
  4. 任何帮助,提示和(为什么不呢?)西红柿都很受欢迎。

2 个答案:

答案 0 :(得分:5)

flatMap也将删除nil值,如果您使用了Haskell(例如),这有点奇怪。

let foo: [String] = ["1","3","5","asd","3"]

let bar: [Int] = foo.flatMap { val in

    guard let int = Int(val) else { return nil}
    return int
}

// bar == [1,3,5,3]

回答你的问题:

  

recipeData in what:我想它就像foreach一样;

forEach采用函数T -> Void,这与在那里发生的事情有点不同。您基本上拥有[AnyObject],并且您将其转换为[Recipe]

  

为什么他们使用flatMap(它们是什么扁平的?);

回到我的初步解释,从片段我会说他们正在删除nil Recipe,所以你只能拥有你能够创建的Recipe

答案 1 :(得分:0)

这不是你问题的完整答案 - 但我努力澄清一个潜在的误解:

  

如果我理解的话,当你需要将二维数组的内容转换成线性数组时,你可以基本使用flatMap。

对于目前的情况可能如此。但是,mapflatMap是更“抽象”的方法,它们将应用于某种“容器”。 mapflatMap执行的实际操作取决于该类型的容器 - 或上下文

例如,mapflatMap是为数组,字典和Optionals定义的。呃,是Optional 容器?是的,它是 - 有点。 以及一些通用 - 例如Foo<T>。这里,“context”是泛型类或结构Foo。它的“元素”是类型T的值。此“容器”中的元素数量可能只有一个 - 或多个。那么,mapflatMap实际上取决于上下文

flatMap可以根据mapflatten来定义。也就是说,flatMap将被实施,以便获得map的结果并将flatten应用于它:

container.map { f($0) }.flatten()

mapflatMap是所谓的组合器 - 函数式编程中的一个术语。组合器可以应用于这些类型的容器并返回一个相同类型的新容器 - 但可能还有另一种元素类型。

组合者 - 顾名思义 - 可以组合在一起形成更复杂的操作。

您现在可以阅读mapflatMapflatten的文档,了解定义它的各种类型,并了解它们的含义