LoginSignup
0
0

More than 1 year has passed since last update.

「A Tour of Go」 の Exercise: Maps を解きました

Last updated at Posted at 2022-07-30

引き続きGo公式のチュートリアル「A Tour of Go」を読み進めています。その中に練習問題がいくつか用意されています。当記事は、Mapに関する練習問題「Exercise: Maps」を解いた記録です。

コード

package main

import (
	"golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
	ret := make(map[string]int)
	left := 0
	for i, val := range s {
		// 空白を見つけてsの left ~ i-1番目まで(i番目は空白) の単語の値をインクリメントして
		// leftを更新する。leftの更新時に+1 しているのは空白をスキップするため
		if ' ' == val {
			ret[s[left:i]]++
			left = i + 1
			// 最後の単語だけ特別扱い
		} else if i == len(s)-1 {
			ret[s[left:]]++
		}
	}
	return ret
}

func main() {
	wc.Test(WordCount)
}

解説

コードとコメントを見ていただけると大体わかると思いますが、できる範囲で解説を書きます。

for i, val := range s

forを使って文字列sを先頭から末尾まで、1文字ずつ巡回します。iはindexで、valはsのi番目の文字です。

ret[s[left:i]]++

ここが肝だと思います。各単語の出現回数を記録します。retはreturnするmapです。WordCountの先頭で定義しています。

s[left:i]

retの中身であるこれはスライスで、文字列sのleft文字目からi-1文字目までの部分文字列を表します。iが指している文字は含まれません。この時iは空白を表しているので、単語の先頭から末尾までの部分列を取得することができます。

// 最後の単語だけ特別扱い
} else if i == len(s) - 1 {
	ret[s[left:]]++
}

これは、iが末尾の文字を指している時は特別に扱う処理です。末尾だけ特別な処理が必要な理由は、スライスが右端を含まないからです。
例えば文字列"Don't repeat your self"を考えます。"your"までは順調に分解できますが、"self"を切り出したい時、iはfを指しているのでそのままスライスしようとすると、"sel"が切り出されてしまいます。
当然切り出したいのは"sel"ではなく"self"なので、特別に処理を設けるに至った次第です。
:の右側に何も書かないと、末尾まで切り出してくれます。

最後に

else if の処理が綺麗じゃないので、良い書き方があったら教えていただけると嬉しいです。
今のところGoって完結でわかりやすい言語だなーと思っております。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0