Tuple から Array
を使いたい場面に遭遇しました。ざっくり言うと以下のようなイメージです。
let tuple = (1, 2, 3, 4)
let array = // 変換
print("\(array)") // [1, 2, 3, 4]
ググってみると熊谷さんのページ *1 にヒットしましたが、Swift の互換性の問題かビルドエラーになってしまいます。このまま頑張ってみる手もあるかもしれませんが、tuple を let
でなく var
で用意しないといけないところや、count
をハードコードしなくてはいけないところが少し残念に思ったので、他の方法を考えてみる事にしました。
var tuple = (1, 2, 3, 4) // 'var'
let buffer = UnsafeBufferPointer(start: &tuple, count: 4)
let array = Array<Int>(buffer) // error
試行錯誤の末に、以下のような関数にたどり着きました。
arrayFromTuple.swift
func arrayFromTuple<T, U>(tuple: T) -> [U] {
return Mirror(reflecting: tuple).children.map { $0.value as! U }
}
簡単に説明すると tuple を Mirror
に食わせてあげると、各タプルの要素を拾うことができるので、これを map
で配列に作り直してあげます。 as! U
を使っているので、想定外の型の値が紛れ込むと落ちますので、ご注意ください。
これを以下のように使えば…と言いたいところですが、これではエラーになってしまいます。 U
の型が決定していないからです。
let tuple = (1, 2, 3, 4)
let array = arrayFromTuple(tuple) // error
そこで 以下のいずれかの書き方をすれば、U
の型が決定するのでビルド可能となります。タプルの型さえ揃っていれば、いくつ連続していても構いません。
let tuple = (1, 2, 3, 4)
let array1 = arrayFromTuple(tuple) as [Int] // [1, 2, 3, 4]
let array2: [Int] = arrayFromTuple(tuple) // [1, 2, 3, 4]
一応、将来の Swift の互換性の問題があるかもしれないので、この記事の執筆の時点の Swift のバージョンを記しておきます。
$ swift --version
Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
*1 Swift でタプルを配列に変換する
https://ez-net.jp/article/D9/m3Nv4a1J/tJo7H-D4ydQ2/