MyDocs

# golangのイテレータを触ってみる

イテレータ

下記の 3 種類が存在する。

func(func() bool)
func(func(K) bool)
func(func(K, V) bool)

slices

All

インデックスと値に対するイテレータを返す。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}
	itr := slices.All(s)

	for i, v := range itr {
		fmt.Println(i, v)
	}
}

// 0 a
// 1 b
// 2 c
// 3 d
// 4 e

Values

スライス要素のイテレータを返す。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}
	itr := slices.Values(s)

	for v := range itr {
		fmt.Println(v)
	}
}

// a
// b
// c
// d
// e

Backward

スライスを逆方向にループするイテレータを返す。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}
	itr := slices.Backward(s)

	for i, v := range itr {
		fmt.Println(i, v)
	}
}

// 4 e
// 3 d
// 2 c
// 1 b
// 0 a

Collect

イテレータから新しいスライスに値を収集する。

下記は、iter.Seq[V] のイテレータを []V の slice に集約している。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}
	itr := slices.Values(s)
	s2 := slices.Collect(itr)
	fmt.Println(s2)
}

// [a b c d e]

AppendSeq

イテレータの値を既存のスライスに追加する。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}
	s2 := []string{"f", "g", "h"}

	itr := slices.Values(s)
	s3 := slices.AppendSeq(s2, itr)

	fmt.Println(s3) // この s3 の型は []string
}

// [f g h a b c d e]

Sorted

イテレータから新しいスライスに値を集め、ソートする。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"z", "a", "b", "c", "d", "e"}

	itr := slices.Values(s)

	s2 := slices.Sorted(itr)

	fmt.Println(s2)
}

// [a b c d e z]

SortedFunc

ソート方法を指定できる。

package main

import (
	"fmt"
	"slices"
	"strings"
)

func main() {
	s := []string{"z", "a", "b", "c", "d", "e"}

	itr := slices.Values(s)

	s2 := slices.SortedFunc(itr, func(a, b string) int {
		return strings.Compare(b, a)
	})

	fmt.Println(s2)
}

// [z e d c b a]

SortedStableFunc

安定したソートアルゴリズムを使う。

package main

import (
	"fmt"
	"slices"
	"strings"
)

func main() {
	s := []string{"z", "a", "b", "c", "d", "e"}

	itr := slices.Values(s)

	s2 := slices.SortedStableFunc(itr, func(a, b string) int {
		return strings.Compare(b, a)
	})

	fmt.Println(s2)
}

// [z e d c b a]

Chunk

スライスを指定された要素数のサブスライスのイテレータとして返す。

package main

import (
	"fmt"
	"slices"
)

func main() {
	s := []string{"a", "b", "c", "d", "e"}

	itr := slices.Chunk(s, 3)

	for s := range itr {
		fmt.Println(s)
	}
}

// [a b c]
// [d e]

maps

All

map から key-value ペアのイテレータを返す。 ただし、順番は保証されていない。

package main

import (
	"fmt"
	"maps"
)

func main() {
	m := map[int]string{
		1: "a",
		2: "b",
		3: "c",
	}

	itr := maps.All(m)

	for i, v := range itr {
		fmt.Println(i, v)
	}
}

// 2 b
// 3 c
// 1 a

Keys

map の key に対するイテレータを返す。 ただし、順番は保証されていない。

package main

import (
	"fmt"
	"maps"
)

func main() {
	m := map[int]string{
		1: "a",
		2: "b",
		3: "c",
	}

	itr := maps.Keys(m)

	for k := range itr {
		fmt.Println(k)
	}
}

// 3
// 1
// 2

Values

map の value に対するイテレータを返す。 ただし、順番は保証されていない。

package main

import (
	"fmt"
	"maps"
)

func main() {
	m := map[int]string{
		1: "a",
		2: "b",
		3: "c",
	}

	itr := maps.Values(m)

	for v := range itr {
		fmt.Println(v)
	}
}

// c
// a
// b

Insert

イテレータから key と value のペアを既存の map に追加する。 重複する key がある場合、上書きされる。

package main

import (
	"fmt"
	"maps"
)

func main() {
	m := map[int]string{
		1: "a",
		2: "b",
		3: "c",
	}

	m2 := map[int]string{
		3: "d",
		4: "e",
		5: "f",
	}

	maps.Insert(m, maps.All(m2))

	fmt.Println(m)
}

// map[1:a 2:b 3:d 4:e 5:f]

Collect

イテレータから新しい map に key-value のペアを収集する。

下記は、iter.Seq[K, V] のイテレータを map[K]V の map に集約している。

package main

import (
	"fmt"
	"maps"
)

func main() {
	m := map[int]string{
		1: "a",
		2: "b",
		3: "c",
	}

	itr := maps.All(m)
	m2 := maps.Collect(itr)

	fmt.Println(m2)
}

// map[1:a 2:b 3:c]