はじめに
おなじみ、A Tour of Go/Exercise: Mapsの例題をしていて、組んだコードです。
Goの書き方として、セオリーを破ってしまっているかもしれませんが、その場合ご助言頂けると嬉しいです。
なお、この関数の仕様としては、
- 英文限定
- スペースなしで「!」や「.」などの記号が付いていた場合は、別の単語としてカウントされる
という感じですので、ご注意を。
今日のコード
func WordCount(s string) map[string]int {
words := strings.Fields(s)
m := map[string]int{}
count := 0
for _, v1 := range words {
for _, v2 := range words {
if v1 == v2 {
count++
}
}
m[v1] = count
count = 0
}
return m
}
解説
strings.Fields関数について
いきなり登場するstrings.Fields
関数の解説については、参考サイトから引用します。
Fieldsは、文字列sをひとつ以上の連続したホワイトスペースで分割し、sの部分文字列の配列を返します。sにホワイトスペースしか含まれていないときは空リストを返します。
簡単に言うと、この関数では内部的にsplit(" ")
的なことをして、配列化しているんですね。
たったこの1行で、単語ごとに切り分けて配列等に格納する作業は完結します。
便利!
2重ループで回す
見ての通り、この関数は2重ループが仕込まれています。
1つ目のループでは、先ほどsrings.Fields
関数で単語単位に切り分けられて、配列格納されたwords
変数の値を1つずつ呼び出します。
2つ目のループで、単語1つ1つをお互いに比較させます。
2つ目のループが一巡するたびに、count
変数は初期化されるため、「数えすぎ問題」に対策してます。
return m
最後に、単語と数をまとめたものを、マップとして返しています。
実行の一例
package main
import (
"fmt"
"strings"
)
func WordCount(s string) map[string]int {
words := strings.Fields(s)
m := map[string]int{}
count := 0
for _, v1 := range words {
for _, v2 := range words {
if v1 == v2 {
count++
}
}
m[v1] = count
count = 0
}
return m
}
func main(){
fmt.Println(WordCount("I have a pen"))
}
map[I:1 a:1 have:1 pen:1]
最後に
あまり複雑な流れではなかったので、サクッとした解説になってしまいました。
また、間違えているところ等ありましたら、ツッコミもらえると嬉しいです。
最後まで、ありがとうございました。