Skip to content

Instantly share code, notes, and snippets.

@KentarouKanno
Last active March 13, 2016 07:43
Show Gist options
  • Save KentarouKanno/c0111a512566cafb3826 to your computer and use it in GitHub Desktop.
Save KentarouKanno/c0111a512566cafb3826 to your computer and use it in GitHub Desktop.
Tuple

Tuple

★ 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment