【Swift】集合型

集合型とは、配列型や辞書型と同じコレクション型の1つで、複数のデータをまとめて入れておける型です。
書式は配列に似ていますが順序を保証しないこと、同一の値を入れられないことが挙げられます。
複数の値を扱いたいが順序は必要なく同一の値を扱わない場合、集合型同士を演算して要素を比較したい場合などが使い道になると思います。

前回は 辞書型 について書きました。

今回は 集合型 について書いていこうと思います。

集合型とは

集合型 とは、配列型や辞書型と同じコレクション型の 1 つで、複数のデータをまとめて入れておける型です。
書式は配列に似ていますが順序を保証しないこと、同一の値を入れられないことが挙げられます。
複数の値を扱いたいが順序は必要なく同一の値を扱わない場合、集合型同士を演算して要素を比較したい場合などが使い道になると思います。

使う時に注意するポイント

  • 要素の順序が保証されない
  • 要素の値は全て異なる値でなければならない
  • 配列型とは違いインデックス番号でアクセスはできない
  • 代入する要素は全て同じ型でなければならない

集合型の書式

var 変数名:Set<要素の型名> = [値, 値, 値, ...]

変数名の後に : で区切って、Set キーワードを書きます。
その後 < > の中に要素の型名を書いて、[ ] の中に全て同じ型の要素を複数書きます。

型推論を使って宣言する場合の書式

var 変数名:Set = [値, 値, 値, ...]

変数名の後に : で区切って、Set キーワードを書きます。
その後 [ ] の中に全て同じ型の要素を複数書きます。
代入した値によって型が推論されます。

※ どちらの書式も配列のリテラルと同じなので Set キーワードが必要です

空の集合型を宣言したい場合

集合型の宣言だけしておいて、後から要素を入れたい場合などに空のまま初期化する事ができます。

//書式1
var 変数名 = Set<要素の型名>()

//書式2
var 変数名:Set<要素の型名> = []

書式 1 と 2 どちらでも空の集合のまま初期化( インスタンス化 )する事ができます。

集合型を使った例

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]

print(type(of: draque)) //Set<String>
print(draque) //["キメラ", "スライム", "ブラウニー"]

型推論を使った集合型の宣言例

//型推論
var drague:Set = ["スライム", "ブラウニー", "キメラ"]

print(type(of: drague)) //Set<String>
print(drague) //["キメラ", "スライム", "ブラウニー"]

集合型は要素の順序を保持しないので、アクセスする度に順序が変わります。

要素を追加する方法

集合型の要素を追加したい場合は、insert メソッドを使います。

集合型の変数名.insert(追加したい値)

要素を追加する例

2 つの要素を追加してみようと思います。

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]
print(type(of: draque)) //Set<String>
print(draque) //["キメラ", "スライム", "ブラウニー"]

//要素を追加
draque.insert("スライムナイト")
draque.insert("おどるほうせき")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

これで要素が 2 つ追加できました。

既存の値を追加してみる

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]
print(type(of: draque)) //Set<String>
print(draque) //["キメラ", "スライム", "ブラウニー"]

//要素を追加
draque.insert("スライムナイト")
draque.insert("おどるほうせき")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

//既存の値を追加
draque.insert("スライム")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

集合型の要素は全て異なる値でなければならないので、追加した値がすでに含まれていた場合、追加しても結果は変わりません。

要素を削除する方法

集合型の要素を削除したい場合は、remove メソッドを使います。

集合型の変数名.remove(削除したい値)

削除したい値はそもそも含まれていない( nil )可能性があります。
なので削除したい値を一度変数に代入して、あったら削除、無かったら代わりの値を出力するといった書き方にすると安全です。

var 変数名 = 集合型の変数名.remove(削除したい値)
集合型の変数名.remove(変数名 ?? 代わりの値)

または
var 変数名:型名? = 削除したい値
集合型の変数名.remove(変数名 ?? 代わりの値)

変数に入れる削除したい値は、無い( nil )可能性がある値なのでこの変数は Optional型 になります。
?? 演算子を使って削除したい値と同一の値が、集合に含まれていればアンラップして削除、含まれていなければ右辺の代わりの値を出力するようにします。

要素を削除する例

2 つの要素を削除してみようと思います。

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]
print(type(of: draque)) //Set<String>
print(draque) //["キメラ", "スライム", "ブラウニー"]

//要素を追加
draque.insert("スライムナイト")
draque.insert("おどるほうせき")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

//既存の値を追加
draque.insert("スライム")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

//要素を削除
//削除したい値を変数に代入する
var removeMonster = draque.remove("キメラ")
var removeMonster2 = draque.remove("スライム")
draque.remove(removeMonster ?? "nil")
draque.remove(removeMonster2 ?? "nil")
print(draque) //["スライムナイト", "おどるほうせき", "ブラウニー"]

集合から 2 つの要素が減っています。
これで安全に 2 つの要素を削除できました。

含まれていない値を削除してみる

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]
print(type(of: draque)) //Set<String>
print(draque) //["キメラ", "スライム", "ブラウニー"]

//要素を追加
draque.insert("スライムナイト")
draque.insert("おどるほうせき")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

//既存の値を追加
draque.insert("スライム")
print(draque) //["スライム", "ブラウニー", "キメラ", "スライムナイト", "おどるほうせき"]

//要素を削除
//削除したい値を変数に代入する
var removeMonster = draque.remove("キメラ")
var removeMonster2 = draque.remove("スライム")
draque.remove(removeMonster ?? "nil")
draque.remove(removeMonster2 ?? "nil")
print(draque) //["スライムナイト", "おどるほうせき", "ブラウニー"]

//含まれていない値を削除
removeMonster = draque.remove("はぐれメタル")
print(removeMonster ?? "nil") //nil

含まれていない値を削除しようとしているので、“nil” が出力されています。

setコードimg

集合型とよく使うメソッドとプロパティ

.contains メソッド

.contains メソッドは、指定した要素が含まれているかどうかを Bool値 で返すメソッドです。
指定した要素があれば true
指定した要素がなければ false が返ってきます。

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]

//.containsメソッド
print(draque.contains("スライム")) //true
print(draque.contains("メタルスライム")) //false

.count プロパティ

.count プロパティは、要素の数を取得する事ができるプロパティです。

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]

//.countプロパティ
print(draque.count) //3

.isEmpty プロパティ

.isEmpty プロパティは、要素が含まれているかどうかを Bool値 で取得することができるプロパティです。
何か要素が入っていれば false
何も入ってなければ true を取得します。
要素が 1 つでも入っていれば false 、空であれば true になります。

var draque:Set<String> = ["スライム", "ブラウニー", "キメラ"]

//.isEmptyプロパティ
print(draque.isEmpty) //false
setコードimg2

集合型の演算

メソッドを使って集合の演算をしていきます。
書式は、

集合A.メソッド名(集合B)

となります。

和集合

和集合を求めるには、union メソッドを使います。
このメソッドは 2 つの集合の を返します。
集合型の要素( 値 )は全て異なる値でなければならないので、重複する値があった場合はカウントしません。

var monsterA:Set = ["スライム", "ブラウニー", "キメラ"]
var monsterB:Set = ["スライム", "キングスライム", "メタルスライム"]
var monsterC:Set<String> = []

//和集合
monsterC = monsterA.union(monsterB)
print(monsterC) //["ブラウニー", "キングスライム", "メタルスライム", "キメラ", "スライム"]

積集合

積集合を求めるには、intersection メソッドを使います。
このメソッドは 2 つの集合の を返します。
2 つの集合の重複した要素( 値 )を返します。

var monsterA:Set = ["スライム", "ブラウニー", "キメラ"]
var monsterB:Set = ["スライム", "キングスライム", "メタルスライム"]
var monsterC:Set<String> = []

//積集合
monsterC = monsterA.intersection(monsterB)
print(monsterC) //["スライム"]

差集合

差集合を求めるには、subtracting メソッドを使います。
このメソッドは、2 つの集合の を返します。
集合 A から 集合 B の重複した要素( 値 )を除いて返します。

var monsterA:Set = ["スライム", "ブラウニー", "キメラ"]
var monsterB:Set = ["スライム", "キングスライム", "メタルスライム"]
var monsterC:Set<String> = []

//差集合
monsterC = monsterA.subtracting(monsterB)
print(monsterC) //["キメラ", "ブラウニー"]

※ 差集合は、集合 A集合 B を反対にすると結果が変わるので注意。

対象差集合

対象差集合を求めるには、symmetricDifferene メソッドを使います。
このメソッドは、2 つの集合の 対象差 を返します。
2 つの集合の重複した要素( 値 )以外を返します。

var monsterA:Set = ["スライム", "ブラウニー", "キメラ"]
var monsterB:Set = ["スライム", "キングスライム", "メタルスライム"]
var monsterC:Set<String> = []

//対象差集合
monsterC = monsterA.symmetricDifference(monsterB)
print(monsterC) //["キメラ", "ブラウニー", "キングスライム", "メタルスライム"]

この他にも Swift にはいろいろなパターンの演算ができるメソッドが用意されています。

setコードimg3

以上 集合型 についてでした。

次回は break文 と continue文 について書いていこうと思います。

実行環境

version
Xcode 14.2 (14C18)
Swift 5.2.4

公式ドキュメント

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/

【Swift】辞書型

辞書型とはkeyと値を紐付けたデータを複数代入できる型のことで、アクセスするときは、keyを指定してそのkeyに紐付く値にアクセスします。
辞書型という名前の通り、辞書を引くような使い方をしたい時などに使います。
配列とは違い、インデックス番号は使えません。

前回は while文 について書きました。

今回は 辞書型 について書いていこうと思います。

辞書型とは

辞書型とは key を紐付けたデータを複数代入できる型のことで、アクセスするときは key を指定して、その key に紐付く にアクセスします。
辞書型という名前の通り、辞書を引くような使い方をしたい時などに使います。
配列とは違い、インデックス番号は使えません。

配列型 についてはこちらの記事で紹介しています。

辞書型の書式

//書式1
[keyの型名:値の型名]

//書式2
Dictionary<keyの型名,値の型名>

書式 1
[ ] の中に key の型名を書いて : で区切って値の型名を書きます。
型推論を使って定義することも可能です。

書式 2
Dictionary キーワードを書いて < > の中に key の型名を書いて , で区切って値の型名を書きます。

辞書型を使った例

//例1(書式1)
var geregere:[String:Int]
geregere = ["HP": 200, "MP": 70, "ATTACK": 120]

print(type(of: geregere)) //Dictionary<String, Int>
print(geregere["HP"]) //Optional(200)

//例2(書式2)
var borongo:Dictionary<String,Int>
borongo = ["HP": 180, "MP": 75, "ATTACK": 125]

print(type(of: borongo)) //Dictionary<String, Int>
print(borongo["MP"]) //Optional(75)

//例3(型推論)
var tiroru = ["HP": 190, "MP": 80, "ATTACK": 130]

print(type(of: tiroru)) // //Dictionary<String, Int>
print(tiroru["ATTACK"]) //Optional(130)

例 3 のように型推論を使って書くこともできます。

辞書型はアクセスすると Optional型 で返ってくる

上の例のアクセスした結果を見ると頭に Optional と付いています。
key を指定してアクセスしていますが、あるか分からない key にアクセスする可能性があるためです。
確実にある key だと分かっている場合であれば強制アンラップ ! でアンラップしてもいいですが、そうでない場合の方が多いと思うので、そういう場合は ?? 演算子を使って nil だった場合に代わりに代入する値を指定した方が安全です。

Optional型アンラップ についてはこちらの記事で紹介しています。

辞書型の変数定義〜アンラップしてアクセスする例

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]
print(suraimu["HP"]) //Optional(100)

まだアンラップ前なので、100 の前に Optional が付いています。
これをアンラップしていきます。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]
print(suraimu["HP"]) //Optional(100)

//アンラップしてアクセスする
print(suraimu["HP"] ?? "nil") //100

?? 演算子を使って、アクセスした key “HP”nil だった場合は文字列の “nil” を代入します。
これで出力されている値は 100 になったので、
Optional型 から Int型 にアンラップすることができました。

次は key に無いものを指定して、結果が変わるか見てみます。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]
print(suraimu["HP"]) //Optional(100)

//アンラップしてアクセスする
print(suraimu["HP"] ?? "nil") //100

//keyに無いものを指定してみる
print(suraimu["Defense"] ?? "nil") //nil

key“Defense” と指定して、keynil だった場合は文字列の “nil” を代入します。
結果は “nil” になります。
“Defense” という key は定義していないので( nil なので )、右辺の “nil” が代わりに代入されます。

dictionaryコードimg

要素の順番は保証されない

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//要素の順番は保存されない
for i in suraimu.keys {
    print(i)
}

//実行結果
/*
ATTACk
HP
MP
*/

配列型とは異なり、辞書型は要素を順番で管理しないので参照するたびに順番が変わります。そのためインデックス番号が使えません。

要素の追加と変更方法

追加または変更の書式

変数名、または定数名[key] = 値

要素の追加

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//要素の追加
suraimu["Defense"] = 10
print(suraimu) //["HP": 100, "ATTACK": 50, "Defense": 10, "MP": 30]

要素の変更

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//要素の追加
suraimu["Defense"] = 10
print(suraimu) //["HP": 100, "ATTACK": 50, "Defense": 10, "MP": 30]

//要素の変更
suraimu["Defense"] = 20
print(suraimu) //["HP": 100, "ATTACK": 50, "Defense": 20, "MP": 30]

追加したい key が既存でなければ追加、key がもし既存のものであれば値の変更になります。

要素の削除

removeValue(forKey:) メソッド

辞書型の要素を削除したいときは、removeValue(forKey:) メソッド を使います。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//要素の追加
suraimu["Defense"] = 10
print(suraimu) //["HP": 100, "ATTACK": 50, "Defense": 10, "MP": 30]

//要素の変更
suraimu["Defense"] = 20
print(suraimu) //["HP": 100, "ATTACK": 50, "Defense": 20, "MP": 30]

//要素の削除
//removeValue(forKey:)メソッド
suraimu.removeValue(forKey: "Defense")
print(suraimu) //["HP": 100, "ATTACK": 50, "MP": 30]

removeValue(forKey:) メソッドの引数に削除したい key 指定します。 key が既存であれば削除することができます。

辞書型とよく使うメソッドとプロパティ

.contains メソッド

.contains メソッドは、指定した要素が含まれているかどうかを Bool値 で返すメソッドです。
指定した要素があれば true
指定した要素がなければ false が返ってきます。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//.containsメソッド
print(suraimu.keys.contains("HP")) //true
print(suraimu.keys.contains("Defense")) //false

.keys プロパティ

.keys プロパティは、key の一覧を取得することができるプロパティです。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//.keysプロパティ
print(suraimu.keys) //["HP", "MP", "ATTACK"]

.values プロパティ

.values プロパティは、値の一覧を取得することができるプロパティです。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//.valuesプロパティ
print(suraimu.values) //[100, 30, 50]

.count プロパティ

.count プロパティは、要素の数を取得することができるプロパティです。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//.countプロパティ
print(suraimu.count) //3

.isEmpty プロパティ

.isEmpty プロパティは、要素が含まれているかどうかを Bool値 で取得することができるプロパティです。
何か要素が入っていれば false
何も入ってなければ true を取得します。
要素が 1 つでも入っていれば false 、空であれば true になります。

var suraimu:[String:Int]
suraimu = ["HP": 100, "MP": 30, "ATTACK": 50]

//.isEmptyプロパティ
print(suraimu.isEmpty) //false
dictionaryコードimg2

辞書型 はコレクション型の 1 つで、配列型 もその 1 つです。
この 2 つの他に 集合型( Set ) というコレクション型もあります。
以上 辞書型 についてでした。

次回は 集合型 について書いていこうと思います。

実行環境

version
Xcode 14.2 (14C18)
Swift 5.2.4

公式ドキュメント

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/

【Swift】配列型

配列型とは、コレクション型の一種で複数のデータをまとめて並べたもののことを言います。
この配列に代入した値のことを要素と言い、この要素をインデックス番号という番号で管理します。
例外を除いて、配列に代入する要素は原則全て同じ型でなければなりません。

前回は スコープ について書きました。

今回は 配列型 について書いていこうと思います。

配列型とは

配列型 とは、コレクション型の一種で複数のデータをまとめて並べたもののことを言います。
この配列に代入した値のことを要素と言い、この要素インデックス番号という番号で管理します。
例外を除いて、配列に代入する要素は原則全て同じ型でなければなりません。

配列の書式

配列の型を明示した書式

//書式1
変数、定数名:Array<型名> = [要素, 要素, 要素, ...]

//書式2
変数、定数名:[型名] = [要素, 要素, 要素, ...]

要素全体は大括弧 [ ] で囲って、要素と要素はカンマ , で区切ります。

配列の型を明示しない書式( 型推論 )

//型推論
変数、定数名 = [要素, 要素, 要素, ...]

配列を使った例

//例1
var a:Array<Int> = [1, 2, 3, 4, 5]
print(type(of: a)) //Array<Int>
print(a) //[1, 2, 3, 4, 5]

//例2
var b:[Int] = [1, 2, 3, 4, 5]
print(type(of: b)) //Array<Int>
print(b) //[1, 2, 3, 4, 5]

//例3(型推論)
var c = [1, 2, 3, 4, 5]
print(type(of: c)) //Array<Int>
print(c) //[1, 2, 3, 4, 5]

上の例の 3 種類は書き方が少し違いますが、どれで書いても同じです。

この例は a , b , c という Int型 の配列にそれぞれ、[1,2,3,4,5] と 5 つの要素を代入している例です。

次に 配列a の要素にインデックス番号でアクセスしていきます。

インデックス番号

インデックス番号は 添え字 とも言います。
インデックス番号は最初の要素から順番に 0 , 1 , 2 と番号が振られていきます。 1 からではなく 0 から始まります。


要素にインデックス番号でアクセスする方法

//書き方例1
var a:Array<Int> = [1, 2, 3, 4, 5]
print(type(of: a)) //Array<Int>
print(a) //[1, 2, 3, 4, 5]

//書き方例2
var b:[Int] = [1, 2, 3, 4, 5]
print(type(of: b)) //Array<Int>
print(b) //[1, 2, 3, 4, 5]

//書き方例3(型推論)
var c = [1, 2, 3, 4, 5]
print(type(of: c)) //Array<Int>
print(c) //[1, 2, 3, 4, 5]

//インデックス番号でアクセス
print(a[0]) //1
print(b[0]) //1
print(c[0]) //1

配列名[インデックス番号] とすることで各要素にアクセスすることができます。
配列 a , b , c にはそれぞれ [1,2,3,4,5] と 5 つの要素が代入されています。
インデックス番号は 0 から始まるので 1 つ目の要素にアクセスするには、a[0] とすれば 配列a の 1 つ目の要素にアクセスできます。

Arrayコードimg

要素の結合と演算

String型 の配列であれば要素同士の結合や、数値型の配列であれば要素同士の演算をする事が出来ます。

文字列の要素を結合

//String型の要素を結合する例
var a:[String] = ["Hello.", "Swift!", "World!"]
print(type(of: a)) //Array<String>
print(a) //["Hello.", "Swift!", "World!"]

//結合
print(a[0] + a[1]) //Hello.Swift!
print(a[0] + a[2]) //Hello.World!

数値型の要素を演算

//数値型の要素を演算する例
var b:[Int] = [1, 2, 3]
print(type(of: b)) //Array<Int>
print(b) //[1, 2, 3]

//演算
print(b[0] + b[1]) //3
print(b[1] * b[2]) //6
Arrayコードimg2

多次元配列

多次元配列とは、配列の中に配列を入れ子することを言います。

多次元配列の書き方

//多次元配列の書き方例
var a:[[Int]] = [[1, 2, 3], [4, 5, 6]]
print(type(of: a)) //Array<Array<Int>>
print(a) //[[1, 2, 3], [4, 5, 6]]

配列の中に複数の配列が格納されています。
次はこの多次元配列の要素にアクセスしてみます。

多次元配列のインデックス番号

多次元配列の要素にインデックス番号でアクセスしてみる。

//多次元配列の書き方例
var a:[[Int]] = [[1, 2, 3], [4, 5, 6]]
print(type(of: a)) //Array<Array<Int>>
print(a) //[[1, 2, 3], [4, 5, 6]]

//多次元配列の要素にインデックス番号でアクセス
print(a[0][1]) //2

上の例だと [1,2,3] は 0 番目の配列で [4,5,6] は 1 番目の配列ということになります。したがって a [0][1]配列a の 0 番目の配列の 1 番目の要素ということになるので、 2 が出力されます。

Arrayコードimg3

以上 配列型 についてでした。

次回は 関数 について書いていこうと思います。

実行環境

version
Xcode 14.2 (14C18)
Swift 5.2.4

公式ドキュメント

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/