为swift编码引入map()和flatMap(), map those arrays

为swift编码引入map()和flatMap(), map those arrays,第1张

概述原文在我博客中: http://zyden.vicp.cc/map-those-arrays/ 欢迎转载,请注明出处,谢谢 这篇文章将讨论将map和flatMap用在Array上 先来看看一段代码: class ListItem { var icon: UIImage? var title: String = "" var url: NSURL! static fu


原文在我博客中: http://zyden.vicp.cc/map-those-arrays/
欢迎转载,请注明出处,谢谢


这篇文章将讨论将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编码引入map()和flatMap(), map those arrays全部内容,希望文章能够帮你解决为swift编码引入map()和flatMap(), map those arrays所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1081562.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-27
下一篇2022-05-27

发表评论

登录后才能评论

评论列表(0条)

    保存