ある slice の操作や検証をするときにスッキリ書く方法を教えてもらったので備忘録。
※ 随時更新(忘れて新しくエントリ書くこともあるかも)
重複する要素を持つ slice を弾きたいとき
func duplicate(arr []string) bool { base := map[string]int{} for _, k := range arr { if i := base[k]; i != 0 { return true } base[k]++ } return false }
base
のような slice において []string{"a", "a", "b"}
みたいな重複する要素を持つ配列を弾きたい時に使います。
ref: https://play.golang.org/p/bW5YFckAZmB
base
の部分も引数に渡してもいいかもしれませんが、ユースケースごとに作ってもいいと思います。
int
を使用したのは重複チェックするなら重複した要素をカウントするのがいいかなと思ったためですね。
ただ、場合によっては int
より効率いいもの使いたい!っていうケースもあると思うのでそしたら bool
を使うのがいいと思います。
typeごとのデータサイズは https://golang.org/src/go/types/sizes.go の basicSizes
を見るとわかります。
func deplicate(arr []string) bool { base := map[string]bool{} for _, k := range arr { if ok := base[k]; ok { return true } base[k] = true } return false }
ref: https://play.golang.org/p/m_g0u9TCWTX
今思うとこっちの方がスッキリしてますね。
意図しない要素をもつ slice を弾きたいとき
func hasInvalidElement(arr []string) bool { base := map[string]int{ "a": 0, "b": 0, "c": 0, } for _, k := range arr { if _, ok := base[k]; !ok { return true } } return false }
base
にない要素をもつ slice を弾きます。
ref: https://play.golang.org/p/Rnc6SFbx1il
このとき要素の重複は許可する場合 e.g. []string{"a", "a", "b", "c"}
には個数のカウントはしません。
そしてこれももっとスッキリ書くなら bool にすると良さそうですね、ってことで書き直してみます。
func hasInvalidElement(arr []string) bool { base := map[string]bool{ "a": true, "b": true, "c": true, } for _, k := range arr { if ok := base[k]; !ok { return true } } return false }
ref: https://play.golang.org/p/SRGe4ZqeTrr
さらにメモリ効率を良くしたい!と言ったときは bool ではなくて struct{}
を使用してもいいかもしれません。
func hasInvalidElement(arr []string) bool { base := map[string]struct{}{ "a": struct{}{}, "b": struct{}{}, "c": struct{}{}, } for _, k := range arr { if _, ok := base[k]; !ok { return true } } return false }
ref: https://play.golang.org/p/Wrpuc0JTupn
組み合わせ
これらを組み合わせて例えば 要素はお互いがユニークかつ決まった要素が入ってるsliceを検証する
と言ったslice の検証要件があったときに以下のようなバリデーションを考えてみます。
func isValid(arr []string) bool { base := map[string]bool{ "a": false, "b": false, "c": false, } for _, k := range arr { if got, ok := base[k]; !ok || got { return false } base[k] = true } return true }
map[string]bool
を使って上記のように書くことが可能です。
ref: https://play.golang.org/p/r8qBfhhhq6m
過去に書いた slice 操作系のエントリ
slice の操作は色々考えてみると結構面白いです。 また何か追加するかもしれません。
過去書いた slice 周りのエントリは以下です。