Swift 具有可选值的元组的Sequence.compactMap等价物

Swift 具有可选值的元组的Sequence.compactMap等价物,swift,Swift,链接序列操作并使用compactMap删除选项可获得外观整洁的代码,如下所示: let images: [UIImage] = strings .compactMap { URL(string: $0) } .compactMap { try? Data(contentsOf: $0) } .compactMap { UIImage(data: $0) } 但是如果我想在最后得到一个元组序列(URL,UIImage),那么compactMap不能帮助删除选项 我发现的一种方法

链接序列操作并使用
compactMap
删除选项可获得外观整洁的代码,如下所示:

let images: [UIImage] = strings
   .compactMap { URL(string: $0) }
   .compactMap { try? Data(contentsOf: $0) }
   .compactMap { UIImage(data: $0) }
但是如果我想在最后得到一个元组序列
(URL,UIImage)
,那么
compactMap
不能帮助删除选项

我发现的一种方法是使用
Optional.map
,它可以工作,但不像上面那样干净

let pairs: [(URL, UIImage)] = strings
   .compactMap { URL(string: $0) }
   .compactMap { url in 
       (try? Data(contentsOf: url)).map { (url, $) }
   }
   .compactMap { t in
      UIImage(data: t.1).map { (t.0, $0) }
   }

是否有更干净的方法(
操作员过载)来实现上述功能?

首先,可以组合最后两个紧凑贴图:

compactMap { try? UIImage(data: Data(contentsOf: $0)) }
单词
try
不必紧跟在一次性呼叫之前。只是任何一次性调用都必须在
try
表达式的范围内

既然你想要一个元组,你应该:

compactMap { ($0, try? UIImage(data: Data(contentsOf: $0))) }
但是,
compactMap
需要一个
(URL,UIImage)?
,而不是
(URL,UIImage?)
。除了模式匹配之外,实在没有办法将一个转换为另一个。为此,您可以编写一个
可选的
初始化器:

extension Optional {
    init<T, U>(_ tuple: (T?, U?)) where Wrapped == (T, U) {
        switch tuple {
        case (let t?, let u?):
            self = (t, u)
        default:
            self = nil
        }
    }
}

let images = strings
   .compactMap { URL(string: $0) }
   .compactMap {
       Optional(($0, try? UIImage(data: Data(contentsOf: $0))))
   }

但是我发现这不太容易理解。

首先,最后两张紧凑地图可以组合在一起:

compactMap { try? UIImage(data: Data(contentsOf: $0)) }
单词
try
不必紧跟在一次性呼叫之前。只是任何一次性调用都必须在
try
表达式的范围内

既然你想要一个元组,你应该:

compactMap { ($0, try? UIImage(data: Data(contentsOf: $0))) }
但是,
compactMap
需要一个
(URL,UIImage)?
,而不是
(URL,UIImage?)
。除了模式匹配之外,实在没有办法将一个转换为另一个。为此,您可以编写一个
可选的
初始化器:

extension Optional {
    init<T, U>(_ tuple: (T?, U?)) where Wrapped == (T, U) {
        switch tuple {
        case (let t?, let u?):
            self = (t, u)
        default:
            self = nil
        }
    }
}

let images = strings
   .compactMap { URL(string: $0) }
   .compactMap {
       Optional(($0, try? UIImage(data: Data(contentsOf: $0))))
   }

但我觉得这不太容易理解。

初始值设定项已经命名为闭包,所以您不需要创建这三个新闭包。@Jessy,您的意思是,我可以做
。compactMap(UIImage(数据:)
?当然可以,但我试图展示与下面代码的并行性。我也不知道抛出
数据(contentsOf:)
初始化器已经命名为闭包,所以您不需要创建这三个新闭包。@Jessy,您的意思是,我可以做
.compactMap(UIImage(Data:))
?当然可以,但我试图展示与下面代码的并行性。我也不知道它如何处理抛出的
数据(contentsOf:)
是的,第一种方法是个好主意。是否有任何方法可以像您使用
mapOptionalTuple
所做的那样,但通过执行运算符重载,可以完成以下操作:
(值,可选)??nil
公共扩展可选
是的,第一种方法是个好主意。是否有任何方法可以像您使用
mapOptionalTuple
所做的那样,但通过执行运算符重载,可以完成以下操作:
(值,可选)??无
公共扩展可选