★ Tuple Basic
// 空のタプル
var empty = ()
//=> ()
// タプルに変数名を使用しない場合
var (name, age, flg) = ("Taro", 10, true)
//=> name = "Taro"
//=> age = 10
//=> flg = true
// ------------------
// タプルに変数名を使用した場合
var tpl = ("Taro", 10, true)
tpl.dynamicType
//=> (String, Int, Bool).Type
// 値の取得、連番でアクセス
tpl.0
//=> "Taro"
tpl.1
//=> 10
tpl.2
//=> true
// 値の代入 ※ letで宣言した場合は代入不可
tpl.1 = 11
tpl.2 = false
// ------------------
// 値に名前を付ける
var tpl = (name: "Taro", age: 10, flg: true)
// 名前でも連番でもアクセス可能
tpl.name
tpl.0
//=> "Taro"
tpl.age
tpl.1
//=> 10
tpl.flg
tpl.2
//=> true
// ------------------
// 『_』ワイルドカードによる値の無視
var (_, age, _) = ("Taro", 10, true)
// 使用しない値は_で無視できる
// ------------------
// ネストしたTuple
var nested = ("1", 2, ("3", 4))
nested.dynamicType
//=> (String, Int, (String, Int)).Type
nested.2.0
//=> "3"
nested.2.1 = 5
// ------------------
// タプルのキーワードが付いている場合は順番を変更して代入できる
var tple1 = ("Taro", 10, true)
var tple2: (String, Int, Bool) = tple1
var tple3: (String, Bool, Int) = tple1
//=> エラー(型が違う為)
var tpl1 = (name: "Taro", age: 10, flg: true)
tpl1.dynamicType
//=> (String, Int, Bool).Type
var tpl2: (age: Int, flg: Bool, name: String) = tpl
tpl2.dynamicType
//=> (Int, Bool, String).Type
// 同じキーワードどうしの代入が可能(キーワードのないものは順番に代入される)
let t: (x: Int, w: Int, y: Int, z: Int) = (y: 5, 8, x: 10, 3)
//=> w = 8, x = 10, y = 5, z = 3
// ------------------
// タプルの比較はできない
// error: binary operator '==' cannot be applied to two '(Int, Int)' operands
let a = (1,2) == (1,2)
★ typealias
// 型を別名で定義
typealias ParsonList = (name: String, age: Int)
var parson: [ParsonList] = [(name: "Taro", age: 10),("Jiro", 15)]
var p1 = parson[0]
p1.name
//=> "Taro"
var p2 = parson[1]
p2.name
//=> "Jiro"
// ---------------------
// typealiasは型なので以下の様に初期化することもできる
let p = ParsonList("name", age: 20)
// p.name => "name"
// p.age => 20
// typealiasにしなかった場合の初期化
let p = (name: String, age: Int)("name", age: 20)
★ タプルを使用したSwap
var a = 10
var b = 20
(b, a) = (a, b)
//=> a = 20, b = 10
// swap関数を使用した場合
swap(&a, &b)
//=> a = 20, b = 10
★ タプルをswitch文で使用する
let tuple = (10, 15)
switch tuple {
case (10, 14) :
print("(10, 14)")
case (_, 16) :
//『_』で値を無視する
print("(_, 16)")
case (1..<10, 10...20) :
// 範囲指定
print("(1..<10, 10...20) ")
case (let a, 17) :
// 変数で値を取得
print("(\(a + 1), 17)")
case (let a, 15) where a <= 10:
// 変数で値を取得 & 変数に条件を付ける
print("(\(a), 15)")
case is (Int, String) :
// 型をマッチングの条件にする
print("(Int, String)")
default:
print("break")
break
}
//=> "(10, 15)\n"
// whereで更に条件を指定する
let tuple = (2, 25)
switch tuple {
case (1, let x) where x > 10:
print ("1, 10以上")
case (2, let y) where y >= 20:
print("2, 20以上")
default:
break
}
★ タプルを順番に取り出し操作する
let values = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
for val in Mirror(reflecting: values).children {
// val は (label: String?, value: Any)のタプル
// val = (Optional(".0"), 0)
}
// 関数化
func generatorForTuple(tuple: Any) -> AnyGenerator<Any> {
return anyGenerator(Mirror(reflecting: tuple).children.lazy.map { $0.value }.generate())
}
for val in generatorForTuple(values) {
val
}
// ---------------
let t = (a: 5, b: "String", c: NSDate())
let mirror = Mirror(reflecting: t)
for (label, value) in mirror.children {
/*
labelの値は
Optional(".0")
Optional(".1")
Optional(".2")
*/
switch value {
case is Int:
print("int")
case is String:
print("string")
case is NSDate:
print("nsdate")
default: ()
}
}
★ タプルの要素数を取得
let values = (1.0, 2, ["a", "b", "c"], NSDate(), [6: "dict"], "7")
Mirror(reflecting: values).children.count
//=> 6
// ------------------
// タプルの要素の型が全て同じ場合は以下の様に取得できる
func countOfTuple<Tuple,U>(p:Tuple, withType type:U.Type) -> Int {
return sizeof(Tuple) / sizeof(type)
}
let values = (0, 1, 2, 3, 4, 5, 6, 7, 8)
countOfUniformTuple(valuess, withType: Int.self)
//=> 9
★ 関数の引数をタプルで置き換える
func method(value1: Int, value2: Int) -> String {
return "Total = \(value1 + value2)"
}
// 通常の呼び出し
let total = method(2, value2: 3)
//=> total = "Total = 5"
// ----------------------
// 引数をタプルで置き換える
var varTuple: (Int, value2: Int) = (2, 3)
var total = method(varTuple as (Int, value2: Int))
//=> "Total = 5"
// varで宣言した場合は変数宣言時に型指定してもキャストが必要
// 上記と同じ
typealias TupleType = (Int, value2: Int)
var varTuple = (2, 3)
var total = method(varTuple as TupleType)
// 型推論
let letTuple = (2, value2: 3)
// 型指定
let letTuple: (Int, value2: Int) = (2, 3)
var total = method(letTuple)
//=> "Total = 5"
// letで宣言した場合は変数宣言時に型指定するとキャストは不要
★ タプルでジェネリクスで使用する
class BaseClass<A,B> {
typealias Element = (A, B)
func addElement(elm: Element) {
print(elm)
}
}
class IntegerClass<B> : BaseClass<Int, B> {
}
let example = IntegerClass<String>()
example.addElement((5, ""))
// Prints (5, "")
★ タプルのOptional
var tuple: (Int, Int)? = nil
tuple.dynamicType
//=> Optional<(Int, Int)>.Type
tuple = (1, 2)
tuple!.0
//=> 1
var tuple: (Int?, Int?) = (nil, nil)
tuple.dynamicType
//=> (Optional<Int>, Optional<Int>).Type
tuple = (1, nil)
tuple.0
//=> 1
tuple.1
//=> nil