LoginSignup
3
2

More than 5 years have passed since last update.

SwiftでArray#flattenする

Last updated at Posted at 2015-02-26

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)))]

つまりelementArray<AnyObject>にキャストすることに失敗し、再帰的に平坦化できなくなっていまっている、ということです。

解決策

そこで、Working with Cocoa Data Typesで説明されている、
「要素の型がクラスのインスタンスでないArrayNSArrayにキャストしたときに、Swiftは暗黙的に要素の型もAnyObject互換な型にキャストする」

let schoolSupplies: NSArray = ["Pencil", "Eraser", "Notebook"]
// schoolSupplies is an NSArray object containing NSString objects

という性質を利用して、elementを間接的にArray<AnyObjec>にキャストしています。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2