プログラミングで文字列操作と同じくらいよく扱うのが、配列やリストの操作です。
複数のデータを管理する配列やリストには、様々な種類があり、用途に応じて使い分けることが重要となります。
本記事では、Goの配列・リストについて、種類と操作方法をまとめました。
プログラミング初心者の方の学習や、忘れてしまった方の復習として、参考にしていただければ幸いです。
記載しているプログラムは、Go1.15.2を使って動作確認をしています。
Goの配列・リスト操作
配列・リスト操作として、以下の内容をとりあげます。
- 配列・リストの種類
- 配列・リストの作成
- 配列・リストから値を取得する
- 配列・リストの長さ(要素数)を取得する
- 配列・リストに要素を追加する
- 配列・リストから要素を削除する
- 配列・リストをコピーする
- 配列・リストをループさせる
- 配列・リストの順番を入れ替える
- 配列・リスト同士を結合する
- 配列・リストを検索する
配列・リストの種類
複数のデータを管理する配列やリストは、プログラミング言語によって様々なデータ構造がサポートされています。
Goでは、以下の3種類を扱うことができます。
- Array型(固定長配列):1つの要素に1つのデータが入る。初期化時に長さを決め、要素の追加や削除ができない。
- Slice型(可変長配列):データの構造はArrayと似ているが、要素の追加や削除が自由にできる。
- Map型(連想配列):keyとvalueからなる構造を持つ。要素の追加や削除が自由にできる。
今回は主に、Sliceに関する操作を中心にまとめていきます。
配列・リストの作成
Arrayの作成方法は、初期値を指定しない方法と指定する方法があります。
初期値を指定しない場合は、要素のオブジェクトで初期化されます。
var a [3]string fmt.Println(a) // -> [ ]
a = [3]string{"Hello", "World", "Go"} fmt.Println(a) // -> [Hello World Go]
Sliceの作成方法も、初期値を指定しない方法と指定する方法があります。
初期値を指定しない場合は、長さ0のSliceとなります。
var s []string fmt.Println(s) // -> []
s = []string{"Hello", "World", "Go"} fmt.Println(s) // -> [Hello World Go]
Mapの作成方法も、初期値を指定しない方法と指定する方法があります。
var m map[int]string fmt.Println(m) // -> map[]
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} fmt.Println(m) // -> map[1:Hello 2:World 3:Go]
配列・リストから値を取得する
Arrayから値を取得するには、取得したい要素のインデックスを指定します。
a = [3]string{"Hello", "World", "Go"} r = a[2] fmt.Println(r) // -> Go
Sliceから値を取得には、取得したい要素のインデックスを指定します。
s = []string{"Hello", "World", "Go"} r = s[2] fmt.Println(r) // -> Go
Mapからvalueを取得するには、取得したい要素のkeyを指定します。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} r = m[3] fmt.Println(r) // -> Go
配列・リストの長さ(要素数)を取得する
Arrayの長さを取得するには、lenを使います。
a = [3]string{"Hello", "World", "Go"} rn = len(a) fmt.Println(rn) // -> 3
Sliceの長さを取得するには、lenを使います。
s = []string{"Hello", "World", "Go"} rn = len(s) fmt.Println(rn) // -> 3
Mapの長さを取得するには、lenを使います。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} rn = len(m) fmt.Println(rn) // -> 3
配列・リストに要素を追加する
Arrayは宣言時に決めた長さを超える要素の追加はできません。
長さの範囲内の要素を変更するには、インデックスを指定した代入します。
a = [3]string{"Hello", "World", "Go"} a[2] = "Golang" fmt.Println(a) // -> [Hello World Golang]
Sliceの末尾に要素を追加するにはappendを使います。
先頭に追加するための関数はないので、追加したい要素のSliceを作成し、それに元のSliceを結合させる方法になります。
s = []string{"Hello", "World", "Go"} rs = append(s, "!!") fmt.Println(rs) // -> [Hello World Go !!]
Mapに要素を追加するにはkeyとvalueを直接指定します。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} m[4] = "!!" fmt.Println(m) // -> map[1:Hello 2:World 3:Go 4:!!]
配列・リストから要素を削除する
Arrayから要素を削除することはできません。
元のArrayから削除したい要素を取り除いた新しいArrayを作ります。
a = [3]string{"Hello", "World", "Go"} ra := a[0:2] fmt.Println(ra) // -> [Hello World]
Sliceから要素を削除するための関数はないので、元のSliceから削除したい要素を取り除いた新しいSliceをつくります。
s = []string{"Hello", "World", "Go"} rs = append(s[:1], s[2:]...) fmt.Println(rs) // -> [Hello Go]
Mapから要素を削除するには、deleteを使います。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} delete(m, 2) fmt.Println(m) // -> map[1:Hello 3:Go]
配列・リストをコピーする
Arrayの要素をコピーするには元のArrayを新しいArrayにそのまま代入します。
a = [3]string{"Hello", "World", "Go"} raa := a fmt.Println(raa) // -> [Hello World Go]
Sliceの要素をコピーするには、copyを使います。
s = []string{"Hello", "World", "Go"} rs = make([]string, len(s)) copy(rs, s) fmt.Println(rs) // -> [Hello World Go]
Mapの要素をコピーするには、専用の関数が用意されていなため、自分でコピーします。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} rm = make(map[int]string) for key, value := range m { rm[key] = value } fmt.Println(rm) // -> map[1:Hello 2:World 3:Go]
配列・リストをループさせる
Arrayをループさせるには、for-rangeを使います。
a = [3]string{"Hello", "World", "Go"} for index, value := range a { fmt.Println(index, value) // -> 0 Hello -> 1 World -> 2 Go }
Sliceをループさせるには、for-rangeを使います。
s = []string{"Hello", "World", "Go"} for index, value := range s { fmt.Println(index, value) // -> 0 Hello -> 1 World -> 2 Go }
Mapをループさせるには、for-rangeを使います。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} for key, value := range m { fmt.Println(key, value) // -> 1 Hello -> 2 World -> 3 Go }
配列・リストの順番を入れ替える
Sliceの要素を入れ替えるには、sortを使います。
s = []string{"Hello", "World", "Go"} sort.Strings(s) fmt.Println(s) // -> [Go Hello World]
Mapの要素を入れ替えるには、keyを取り出してSliceに変換してソートし、ソートしたkeyでvalueを取り出します。
m = map[int]string{3: "Go", 1: "Hello", 2: "World"} var keys []int for key := range m { keys = append(keys, key) } sort.Ints(keys) for _, key := range keys { fmt.Println(key, m[key]) // -> 1 Hello -> 2 World -> 3 Go }
配列・リスト同士を結合する
Sliceの結合は、appendを使います。
s1 := []string{"Hello", "World"} s2 := []string{"Go", "!!"} rs = append(s1, s2...) fmt.Println(rs) // -> [Hello World Go !!]
Mapの結合は、専用の関数が用意されていなため、ループで地道に追加していきます。
m1 := map[int]string{1: "Hello", 2: "World"} m2 := map[int]string{3: "Go", 4: "!!"} rm = make(map[int]string) for key, value := range m1 { rm[key] = value } for key, value := range m2 { rm[key] = value } fmt.Println(rm) // -> map[1:Hello 2:World 3:Go 4:!!]
配列・リストを検索する
ArrayやSliceに指定した値が含まれているかどうかを検索するための専用の関数はありません。
ループで地道に一致するものがあるか探します。
Mapで指定したkeyが含まれているかどうかは、取り出したときの2つ目の戻り値に結果が返ってきます。
m = map[int]string{1: "Hello", 2: "World", 3: "Go"} _, rb := m[1] fmt.Println(rb) // -> true
配列・リストの操作はやりたい処理によって使うメソッドを変えよう
配列やリストの操作には、同じ結果を得られる方法が、処理を組み合わせることによって何通りもあります。
ですが、特にループの場合には、処理の仕方によってはパフォーマンスが悪いこともあります。
どんなメソッドを使うのかは、やりたい処理によって適宜変えられるように、日頃からたくさん引出しを持っておくことをおすすめします。
今回は、Goの配列・リスト操作についてまとめました。
参考になれば幸いです。
コメント