为swift编码引入map()和flatMap(), map those arrays
2015-12-17 18:28
411 查看
原文在我博客中: http://zyden.vicp.cc/map-those-arrays/
欢迎转载,请注明出处,谢谢
这篇文章将讨论将map和flatMap用在Array上
先来看看一段代码:
这是很常见的for in遍历
因此,在以上代码这种情况下,我们可以对jsonItems这个字典数组使用map,并提供一个转换规则来让每个dictionary转换成为ListItem实例,而不是像以前那样去使用fon in来做循环,如下:
这看上去的一个转换的func,让我们解决了将jsonItems数组里的所有dictionary转换成ListItem对象的需求,而跟以前oc的做法不同,这避免了使用一个媒介的mutableArray来做,一步到位,更直观逻辑。如果可以,请尽量避免使用可变的那种情形。
更重要的是我们url的类型是NSURL!,一旦将一个不合法的值(nil)赋给item.url(NSURL!),我们的代码自然就crash了。
于是我们想到了使用guard语句的安全操作, 如果出现了异常数据,我们就返回一个nil的ListItem对象,去避免返回一个残缺的ListItem对象,同时避免了crash。
但是如果我们使用NSDictionary -> ListItem?这种新的转换的话,如果我们包含不合法数据不合法的NSDictionary,将会得到一个包含nil的[ListItem?],虽然强于以前但并不是一个最佳的解决办法。
flatMap()与map()其实非常相似,map()的规则是T->U,而flatMap()的规则是T->U?,而且如果转换的结果是nil的话,flatMap()是不会将其添加到输出的array中的。
因此可以说flapMap()就好像你去使用map(),然后扁平化(faltten)地从结果中去除了那些nil的内容。
综上,对于我们的例子我们可以改变成一下代码:
现在,我们只返回了在各种key存在且合法(guard)的情况下转换出来的ListItem对象,包括url(NSURL!)必须不为nil的情况也处理到了。
我们消除了数据质量的问题和一些虚假数据的风险,这样就更加完美且安全了。
对于guard的用法,可以参考我这篇文章:http://zyden.vicp.cc/swift-optional-value/
欢迎转载,请注明出处,谢谢
这篇文章将讨论将map和flatMap用在Array上
先来看看一段代码:
class ListItem { var icon: UIImage? var title: String = "" var url: NSURL! static func listItemsFromJSONData(jsonData: NSData?) -> [ListItem] { guard let nonNilJsonData = jsonData, let json = try? NSJSONSerialization.JSONObjectWithData(nonNilJsonData, options: []), let jsonItems = json as? Array<NSDictionary> else { // If we failed to unserialize the JSON or that JSON wasn't an NSArray, // then bail early with an empty array return [] } var items = [ListItem]() for itemDesc in jsonItems { let item = ListItem() if let icon = itemDesc["icon"] as? String { item.icon = UIImage(named: icon) } if let title = itemDesc["title"] as? String { item.title = title } if let urlString = itemDesc["url"] as? String, let url = NSURL(string: urlString) { item.url = url } items.append(item) } return items } }
这是很常见的for in遍历
map简介()
map()是Array的一个方法,他接收一个改变数组内每个元素的规则的function作为参数,返回值是一个所有元素改变后的集合。这让我们很方便地用每个x->y的转换来实现[x]->[y]的转换,而不是像以前那样去创建一个临时的mutableArray来做这样的工作。因此,在以上代码这种情况下,我们可以对jsonItems这个字典数组使用map,并提供一个转换规则来让每个dictionary转换成为ListItem实例,而不是像以前那样去使用fon in来做循环,如下:
return jsonItems.map { (itemDesc: NSDictionary) -> ListItem in let item = ListItem() if let icon = itemDesc["icon"] as? String { item.icon = UIImage(named: icon) } if let title = itemDesc["title"] as? String { item.title = title } if let urlString = itemDesc["url"] as? String, let url = NSURL(string: urlString) { item.url = url } return item }
这看上去的一个转换的func,让我们解决了将jsonItems数组里的所有dictionary转换成ListItem对象的需求,而跟以前oc的做法不同,这避免了使用一个媒介的mutableArray来做,一步到位,更直观逻辑。如果可以,请尽量避免使用可变的那种情形。
数据质量
与我们以前的做法还有一个不同之处,即使有不正确的输入数据,就会有无效的dictionary访问,但我们依然也是一样地创建了ListItem对象并都保存在其最终的array中了,这样就会有一些不完整的ListItem对象(一部分属性为nil)。更重要的是我们url的类型是NSURL!,一旦将一个不合法的值(nil)赋给item.url(NSURL!),我们的代码自然就crash了。
于是我们想到了使用guard语句的安全操作, 如果出现了异常数据,我们就返回一个nil的ListItem对象,去避免返回一个残缺的ListItem对象,同时避免了crash。
return jsonItems.map { (itemDesc: NSDictionary) -> ListItem? in guard …/* condition for valid data */… else { return nil } let realValidItem = ListItem() … /* fill the ListItem with the values */ return realValidItem }
但是如果我们使用NSDictionary -> ListItem?这种新的转换的话,如果我们包含不合法数据不合法的NSDictionary,将会得到一个包含nil的[ListItem?],虽然强于以前但并不是一个最佳的解决办法。
使用 flatMap()
好了,这时候flatMap()就来解决这个问题了。flatMap()与map()其实非常相似,map()的规则是T->U,而flatMap()的规则是T->U?,而且如果转换的结果是nil的话,flatMap()是不会将其添加到输出的array中的。
因此可以说flapMap()就好像你去使用map(),然后扁平化(faltten)地从结果中去除了那些nil的内容。
综上,对于我们的例子我们可以改变成一下代码:
return jsonItems.flatMap { (itemDesc: NSDictionary) -> ListItem? in guard let title = itemDesc["title"] as? String, let urlString = itemDesc["url"] as? String, let url = NSURL(string: urlString) else { return nil } let li = ListItem() if let icon = itemDesc["icon"] as? String { li.icon = UIImage(named: icon) } li.title = title li.url = url return li }
现在,我们只返回了在各种key存在且合法(guard)的情况下转换出来的ListItem对象,包括url(NSURL!)必须不为nil的情况也处理到了。
我们消除了数据质量的问题和一些虚假数据的风险,这样就更加完美且安全了。
对于guard的用法,可以参考我这篇文章:http://zyden.vicp.cc/swift-optional-value/
thanks !
相关文章推荐
- 窥探Swift之类的继承与类的访问权限
- Swift语法备注
- Swift Moya
- iOS SDK详解之NSPredicate(Swift)
- swift学习笔记之-方法部分
- Swift与Objc(传统语言)的异同
- swift学习记录(函数--嵌套函数)
- Swift 基本运算符(笔记)
- [ios][swift]swift 怎么去除 optional
- swift学习记录(函数--输入输出参数)
- swift学习记录(函数)
- Swift版音乐播放器(简化版),swift音乐播放器
- Swift---- 可选值类型(Optionals) 、 断言(Assertion) 、 集合 、 函数
- Swift----方法 、 下标 、 继承 、 初始化 、 析构方法 、 可选链
- Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性
- Swift-----类型转换 、 嵌套类型 、 扩展 、 协议 、 访问控制
- Swift基础语法 、 元组(Tuple)
- Swift 基本概念(笔记)
- 《Swift 的数组 (Array)的声明和 数组的基本操作详解 和 元组(Tube) 的声明和使用》
- swift学习记录(跳转语句)