Swift 有没有办法测试数组';s类型是可选的吗?

Swift 有没有办法测试数组';s类型是可选的吗?,swift,Swift,假设我想在Array上编写一个方法,如果其类型是非可选的,则返回数组的副本;如果其类型是可选的,则返回未包装值的子数组。为此,我想我需要能够测试数组的类型T是否为可选类型。例如,在以下两种情况下,这只返回数组的副本: extension Array { func unwrapped() -> Array<T> { return filter({ var x: T? = $0 return x

假设我想在
Array
上编写一个方法,如果其类型是非可选的,则返回数组的副本;如果其类型是可选的,则返回未包装值的子数组。为此,我想我需要能够测试数组的类型
T
是否为可选类型。例如,在以下两种情况下,这只返回数组的副本:

extension Array {        
    func unwrapped() -> Array<T> {
        return filter({
            var x: T? = $0
            return x != nil
        })
    }
}

我不是在寻找解决那个具体问题的办法。相反,我想知道是否有一种方法可以在数组扩展中确定其类型是否是可选的,这在许多不同的方便方法中可能很有用。

一种可能的解决方案是使用全局函数而不是扩展;然后可以使用两个定义重载,一个用于非可选类型,另一个用于可选类型:

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

unwrapped([1, 2, 3, 4, 5]) // -> [1, 2, 3, 4, 5]
unwrapped([1, 2, 3, nil, 5]) // -> [1, 2, 3, 5]
func展开(a:[T])->[T]{返回a}
函数展开(a:[T?])->[T]{
返回一个.filter{$0!=nil}.map{$0!}
}
未包装([1,2,3,4,5])/->[1,2,3,4,5]
未包装([1,2,3,nil,5])/->[1,2,3,5]
我不确定这是否保证有效;如果有人能在Swift指南中找到一个破绽的案例或者说它总是正确的地方,那将是很有趣的

另请参见中的讨论。

使用减少:

let unwrapped = foo.reduce([String]()) {
    if let bar = $1 as String? { return $0 + [bar] }
    return $0
}
如果原始文件是非可选的,则返回一个副本;如果原始文件是可选的,则返回非nil unwrapped值的子数组。要做到这一点,您不需要知道数组是否包含optionals

如果数组至少包含一个值,则可以确定该值是否为可选值,如下所示:

extension Array {
    func optTest() {
        switch reflect(self[0]).disposition {
            case .Optional:
                println("I am an optional")
            default:
                break
        }
    }
}

您只需要测试第一个值。但是我还没有弄明白如何测试空数组-我想你可以向其中添加一个元素,然后测试该元素…

可以扩展
数组
结构以返回其泛型类型,然后

这个例子是为Swift 2设计的,但我相信它应该在以前的版本中也能起到类似的作用

protocol OptionalProtocol {}

extension Optional : OptionalProtocol {}

extension Array {
    func elementType() -> Any.Type {
        return Element.self
    }
}

[String]().elementType() is OptionalProtocol.Type  // false
[String?]().elementType() is OptionalProtocol.Type // true
特定于Swift 2,可以完全放弃
数组
扩展,因为typealias允许访问
元素
类型:

protocol OptionalProtocol {}

extension Optional : OptionalProtocol {}

[String]().dynamicType.Element.self is OptionalProtocol.Type  // false
[String?]().dynamicType.Element.self is OptionalProtocol.Type // true
为此,我想我需要能够测试数组的类型T是否是可选类型

不,你不必-只需使用平面地图

let foo: [String?] = [nil, "bar", "baz"]
let foo2: [String] = ["bar", "baz"]

foo.flatMap{$0}
foo2.flatMap{$0}
// yield both ["bar", "baz"] and are of type Array<String>
let foo:[String?]=[nil,“bar”,“baz”]
让foo2:[字符串]=[“bar”,“baz”]
foo.flatMap{$0}
foo2.flatMap{$0}
//同时产生[“bar”、“baz”]和数组类型

reduce方法相当于filter/map方法,只有在我知道数组类型的情况下才有效。我看不到在数组扩展中推广这种方法的方法。
disposition
很有趣。这似乎对非空数组有效。在REPL中测试时,
unwrap
函数似乎返回数组的副本,但选项未展开
[nil as String?,“foo”].unwrap()$R5:[String?]=2个值{[0]=nil[1]=“foo”}
是的,这可以打开数组中的所有值,这很方便。奇怪的是,它们只作为全局函数工作。如果我将它们定义为数组扩展中的静态函数,则调用Array.unwrapped会出现错误
无法使用类型为
的参数调用“unwrapped”。不幸的是,此时不允许使用类似
扩展数组
的内容(甚至是代码>扩展数组< /COD>,虽然我不确定它会允许你做任何有用的事情)。这是C++模板系统展现出更大灵活性的一个领域。我希望Swift有一天能到达那里……另一个有趣的点——调用<代码>未封装的<代码>只在扩展之外工作。调用<代码>解包(自我)来自数组扩展中的函数总是调用非可选版本并仅返回self。这很有意义,因为
T
是扩展中的通用参数。您可能可以使用我链接的问题中的技术来解决这个问题。。。
let foo: [String?] = [nil, "bar", "baz"]
let foo2: [String] = ["bar", "baz"]

foo.flatMap{$0}
foo2.flatMap{$0}
// yield both ["bar", "baz"] and are of type Array<String>