假设我们定义了一组选项:
var arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
我可以强行打开它:var arrayForCrash = arrayOfOptionals.map { $0! }
但这会让app崩溃,还有其他任何简短的方法(没有明确展开)我如何解开一个可选数组?
答案 0 :(得分:92)
此解决方案将为您提供一个新数组,其中包含所有值,并且所有值都已被过滤掉。
Swift 4.1:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.compactMap { $0 }
Swift 2.0:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.flatMap { $0 }
Swift 1.0:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.filter { $0 != nil }.map { $0! }
答案 1 :(得分:9)
由于它是一个可选项数组,因此有些条目可能是nil
。使用 nil coalescing运算符将!
转换为空字符串,而不是强制解包。
nil
答案 2 :(得分:3)
虽然您可以使用flatMap { $0 }
来删除nils,但是flatMap实际上是一个功能更强大的函数,并且有一个重载版本可以完成不同的操作(例如将[[Int]]
展平为[Int]
) 。如果你不小心,你可能会意外调用错误的功能。
我建议在SequenceType上使用扩展来删除nils。如果您使用removeNils()
,您将能够基本上执行以下操作:
[1, nil, 2].removeNils() == [1, 2]
它的工作原理是使Optional
符合OptionalType
协议,该协议允许扩展包含SequenceType
值的Optional
。
有关详细信息,请参阅original answer I posted。
答案 3 :(得分:1)
我接受了@Cenny的回答,决定让操作员离开它:
prefix operator <!> {}
prefix func <!> <T>(array: [T?]) -> [T] {
return array.filter{ $0 != nil }.map{ $0! }
}
我用它来解析JSON对象数组并过滤那些失败的对象:
static func parse(j: JSONArray) -> [Agency]? {
return <!>j.map { self.parse($0) }
}
Swift 2+的更新:
使用flatMap
运算符,它只返回非零对象
答案 4 :(得分:0)
怎么样:
import Foundation
var test: [String!] = ["this","is","a",nil,"test"]
for string in test {
if string != nil {
print(string)
}
}
输出为thisisatest
。
如果我理解正确,请使用[String!]
。
答案 5 :(得分:0)
快捷键4
易于阅读和安全的方法来过滤任何序列的钉子
protocol OptionalProtocol {
associatedtype Wrapped
var optional: Wrapped? { get }
}
extension Optional: OptionalProtocol {
var optional: Wrapped? {
return self
}
}
extension Sequence where Element: OptionalProtocol {
var removingOptionals: [Element.Wrapped] {
return self.compactMap { $0.optional }
}
}
用法
let array: [Int?] = [1, 2, nil, 3, 4, nil]
print(array.removingOptionals) // prints [1, 2, 3, 4], has type [Int]
答案 6 :(得分:0)
更有趣的是,如何解开可选值的可选数组。在使用JSON时,进行处理非常重要,因为JSON可能包含某物数组的null
值。
示例:
{ "list": null }
// or
{ "list": [null, "hello"] }
要填充Swift结构,我们可以有一个模型:
struct MyStruct: Codable {
var list: [String?]?
}
为了避免将String??
作为第一项工作,我们可以:
var myStruct = try! JSONDecoder.init().decode(MyStruct.self, from: json.data(using: .utf8)!)
let firstItem: String? = s1.list?.compactMap { $0 }.first
有了compactMap { $0 }
,我们可以避免
let i2: String?? = s1.list?.first
compactMap { $0 }
等效于filter { $0 != nil }. map { $0! }