Array#flatten
以下のような実装をしてみました。
extension Array {
func flatten() -> [AnyObject] {
var flattenArray = [AnyObject]()
for element in self {
if let element = element as? NSArray as? [AnyObject] {
flattenArray += element.flatten()
} else {
flattenArray.append(element as NSObject)
}
}
return flattenArray
}
}
var temp = [1, [2, 3, 4, [5, 6]]]
var flat = temp.flatten()
println(flat) // [1, 2, 3, 4, 5, 6]
実装について補足
if let element = element as NSArray as? [AnyObject] {}
という処理について少し補足します。
まず、なんでNSArrayにキャストしてからArray<AnyObject>にキャストしているんだ?
と疑問に思われるかもしれませんが、
これはT型(placeholder type)のelementを直接Array<AnyObject>へキャストしようとすると、elementの実際の型がArray<AnyObject>だったとしてもnilになるためです。
if let element = element as? [AnyObject] {}とした場合、この挙動は以下のような期待していない結果を招きます。
var temp:[Any] = [[1, [2, 3, 4, [5, 6]]]]
var flat = temp.flatten()
println(flat) // [(1,(2,3,4,(5,6)))]
つまりelementをArray<AnyObject>にキャストすることに失敗し、再帰的に平坦化できなくなっていまっている、ということです。
解決策
そこで、Working with Cocoa Data Typesで説明されている、
「要素の型がクラスのインスタンスでないArrayをNSArrayにキャストしたときに、Swiftは暗黙的に要素の型もAnyObject互換な型にキャストする」
let schoolSupplies: NSArray = ["Pencil", "Eraser", "Notebook"]
// schoolSupplies is an NSArray object containing NSString objects
という性質を利用して、elementを間接的にArray<AnyObjec>にキャストしています。