在Swift中展开稀疏数组

时间:2014-11-24 03:11:18

标签: arrays swift optional xcode6.1

我想写一个Array的扩展名,它可以安全地返回自己的解包版本。

我可以使用像这样的通用方法:

func unwrapElements<T>(array: [T?]) -> [T] {
    let filtered: [T?] = array.filter{ $0 != nil }
    let unwrapped: [T] = filtered.map { $0! }
    return unwrapped
}

我可以这样称呼它:

let sparseNames: [String?] = ["alice", "bob", nil, "doug", nil, nil, "george", "hubert"]
let names: [String] = unwrapElements(sparseNames)

其中names最终为["alice", "bob", "doug", "george", "hubert"],并且可以安全地迭代并处理每个元素。

但是,我想这样称呼它:

let names = sparseNames.unwrapElements()

我看过一些类似的问题(like this one)但是他们没有解决如何将方法创建为扩展名。


(这是用Xcode6.1标记的,表示我正在使用的Swift版本)


注意:Swift 1.2 Beta 3引入了flatMap函数,它有助于可选地链接数组。看到这个优秀的blog post here

3 个答案:

答案 0 :(得分:3)

你现在无法在Swift中做到这一点。要将该函数添加为Array的扩展名,您必须以某种方式标记它只能使用某些类型的数组进行调用:具有可选值的那些作为亚型。不幸的是,您无法进一步专门化泛型类型,因此全局函数是唯一可行的方法。

这与Array具有sort方法的原因相同,该方法将比较函数作为参数,但它没有sort只有{#1}}工作&#34;如果数组中有Comparable个成员 - 要获得这种功能,你必须查看顶级排序:

func sort<T : Comparable>(inout array: [T])

答案 1 :(得分:1)

您是否尝试过使用filtermap

let array: [String?] = ["Hello", nil, "World"]

let unwrapped = array.map{$0 ?? nil}.filter{$0 != nil}.map{$0!}

println("unwrapped: \(unwrapped)")
// prints "unwrapped: [Hello, World]"

如果可能,第一个map使用Nil Coalescing Operator解包。虽然,我返回nil,因为以下过滤器会删除所有nil值。最后map执行实际解包。

答案 2 :(得分:0)

你可以这样做。方法如下:

extension Array {
    func catOptionals<A>() -> [A] where Element == A? {
        return self.flatMap{ $0 }
    }
}