🗺️
Go言語のmapについて、問題を眺めながら超基礎部分だけをまとめる
問題
整数のスライスを引数に取り、スライスの中で最も頻繁に現れる要素を返す関数をGoで実装してください。同じ頻度の要素が複数ある場合は、その中のどれか一つを返してください。
- 入力: [1, 2, 2, 3, 3, 3, 4] の場合、出力は 3
- 入力: [5, 5, 6, 6, 7, 7, 7, 6] の場合、出力は 6 か 7 (どちらでも正解)
map
とは?
Go言語のGoの map
は、 キーと値のペア を保持するデータ構造です。キーを使って値にアクセスしたり、キーに対応する値を変更したり削除したりすることができます。
基本的な構文
var m map[KeyType]ValueType
-
KeyType
: キーのデータ型(例:int
,string
,float64
など)。 -
ValueType
: 値のデータ型(例:int
,string
,bool
など)。
たとえば、map[int]string
はキーが int
で、値が string
のマップを意味します。
mapの作成方法
-
make関数で作成
m := make(map[int]string)
-
リテラルを使って作成
m := map[int]string{ 1: "One", 2: "Two", 3: "Three", }
要素の追加・アクセス・削除
1. 要素の追加
mapに要素を追加するには、キーを指定して値を代入します。
m := make(map[int]string)
m[1] = "One" // キー1に値"One"を追加
m[2] = "Two" // キー2に値"Two"を追加
2. 要素の取得
キーを使って要素にアクセスします。
value := m[1] // "One" を取得
3. 要素の削除
delete
関数を使って、特定のキーの要素を削除します。
delete(m, 1) // キー1の要素を削除
4. キーの存在確認
Goでは、キーが存在するかどうかを確認するために、2つの戻り値を使うことができます。
value, exists := m[1]
if exists {
fmt.Println("キー1が存在します:", value)
} else {
fmt.Println("キー1は存在しません")
}
mapの便利な使い方
-
ループで全要素を取得
range
を使って、map の全要素に対してループを回すことができます。for key, value := range m { fmt.Println(key, value) }
このようにして、全てのキーとその対応する値を処理できます。
-
mapの長さを取得
len
関数で map の要素数を取得できます。fmt.Println(len(m)) // mapに入っているキーと値のペアの数を返す
mapの使用例
以下は、整数をキーとして、その平方数を値として保存するmapの例です。
package main
import "fmt"
func main() {
squares := make(map[int]int)
// キーと値の追加
squares[1] = 1
squares[2] = 4
squares[3] = 9
// 値の取得
fmt.Println("2の平方:", squares[2]) // 4が出力される
// mapのループ
for key, value := range squares {
fmt.Printf("キー: %d, 値: %d\n", key, value)
}
// 要素の削除
delete(squares, 2)
// 削除後の確認
if _, exists := squares[2]; !exists {
fmt.Println("キー2は存在しません")
}
}
問題を解いてみる
では、先ほどの問題(最も頻繁に現れる要素を見つける問題)の解説を行います。
package main
import "fmt"
func mostFrequent(num_slice []int) int {
// 出現回数を保存するマップを作成
frequencyMap := make(map[int]int)
// スライス内の要素の出現回数を数える
for _, num := range num_slice {
frequencyMap[num]++ // 既にkeyが存在していればvalueを+1、存在していなければ新たにkeyを作成しvalueを1にする
}
// 最も頻繁に出現する要素を見つける
mostFrequentNum := num_slice[0] // 最も頻繁に出現する要素
maxCount := 0 // 最も頻繁に出現する要素の出現回数
// マップをループして最大の出現回数を持つ要素を探す
for num, count := range frequencyMap {
// 出現回数が最大の要素を更新
if count > maxCount {
mostFrequentNum = num // 最も頻繁に出現する要素を更新
maxCount = count // 最も頻繁に出現する要素の出現回数を更新
}
}
return mostFrequentNum
}
func main() {
fmt.Println(mostFrequent([]int{1, 2, 2, 3, 3, 3, 4})) // 3が出力される
fmt.Println(mostFrequent([]int{5, 5, 6, 6, 7, 7, 7, 6})) // 6または7が出力される
}
解説
1. マップの作成
frequencyMap := make(map[int]int)
-
frequencyMap
は整数をキーに、出現回数を値に持つマップです。このマップを使って、スライス内の各要素が何回出現したかを記録します。
2. 出現回数を数える
for _, num := range num_slice {
frequencyMap[num]++
}
- スライス
num_slice
の各要素num
をループで取り出し、frequencyMap[num]
に対応する値をインクリメント(1増やす)します。これで各要素の出現回数を記録します。
3. 最も頻繁に出現する要素を見つける
mostFrequentNum := num_slice[0]
maxCount := 0
for num, count := range frequencyMap {
if count > maxCount {
mostFrequentNum = num
maxCount = count
}
}
- 最初に
mostFrequentNum
にスライスの最初の要素を仮の最頻出要素として設定し、maxCount
には0を設定します。 - 次に、マップ
frequencyMap
をループして各要素の出現回数をチェックし、maxCount
より大きい出現回数があれば、その要素を新しいmostFrequentNum
に更新します。
4. 結果の返却
return mostFrequentNum
- ループが終わった後に、
mostFrequentNum
には最も頻繁に出現する要素が格納されているので、それを返します。
ポイント
- mapの使い方: map を使って、要素の出現回数を効率的に記録し、後で最頻出要素を探すために利用しています。
- ループ処理: 最初にスライス内の各要素の出現回数を数え、その後に最大の出現回数を持つ要素を探す2段階のループ処理です。
このように、map を使うことで効率的に要素の出現回数を管理し、最頻出要素を見つけることができます。
Discussion