golang实现C++ STL迭代器与算法功能的插件库iter的使用
Golang实现C++ STL迭代器与算法功能的插件库iter的使用
iter是一个Go语言实现的C++ STL迭代器和算法库,它提供了超过100种算法,几乎涵盖了C++17之前的所有STL算法。这个库的主要目标是减少手写循环,使代码更具表达性。
特点
-
非侵入式设计:iter不引入新的容器类型,而是重用Go现有的容器(如slice、string、list.List等),并通过迭代器适配它们以使用算法。
-
完整算法支持:包含几乎所有C++17之前的算法,如AllOf、FindIf、Accumulate、Shuffle、Sample、Partition等。
-
性能优化:库中的实现包含了一些不易察觉的性能优化。
安装
go get github.com/disksing/iter
示例代码
1. 打印list.List
l := list.New()
GenerateN(ListBackInserter(l), 5, IotaGenerator(1))
Copy(lBegin(l), lEnd(l), IOWriter(os.Stdout, "->"))
// 输出:
// 1->2->3->4->5
2. 反转字符串
s := "!dlrow olleH"
fmt.Println(MakeString(StringRBegin(s), StringREnd(s)))
b := []byte(s)
Reverse(begin(b), end(b))
fmt.Println(string(b))
// 输出:
// Hello world!
// Hello world!
3. 原地去重
in := []int{3, 2, 1, 4, 3, 2, 1, 4, 1}
Sort(begin(in), end(in))
Erase(&in, Unique(begin(in), end(in)))
fmt.Println(in)
// 输出:
// [1 2 3 4]
4. 计算通道中所有整数的和
ch := make(chan int)
go func() {
CopyN(IotaReader(1), 100, ChanWriter(ch))
close(ch)
}()
fmt.Println(Accumulate(ChanReader(ch), ChanEOF, 0))
// 输出:
// 5050
5. 移除字符串中的连续空格
str := " a quick brown fox "
var sb StringBuilderInserter
UniqueCopyIf(sBegin(str), sEnd(str), &sb,
func(x, y Any) bool { return x.(byte) == ' ' && y.(byte) == ' ' })
fmt.Println(sb.String())
// 输出:
// a quick brown fox
6. 从通道中收集前N个最大元素
top := make([]int, 5)
PartialSortCopyBy(ChanReader(ch), ChanEOF, begin(top), end(top),
func(x, y Any) bool { return x.(int) > y.(int) })
Copy(begin(top), end(top), IOWriter(os.Stdout, ", "))
7. 打印所有排列组合
s := []string{"a", "b", "c"}
for ok := true; ok; ok = NextPermutation(begin(s), end(s)) {
fmt.Println(s)
}
// 输出:
// [a b c]
// [a c b]
// [b a c]
// [b c a]
// [c a b]
// [c b a]
优势
-
代码简洁:使用算法替代简单循环可以使代码更简洁易懂。
-
正确性保证:一些算法虽然不复杂,但正确实现并不容易,重用代码可以更容易保证正确性。
-
复杂算法:STL包含一些可能需要数小时才能正确实现的复杂算法,手动实现不切实际。
-
性能优化:库中的实现包含了一些性能优化,如MinmaxElement通过一次比较两个元素显著减少了比较次数。
iter库是Go中实现STL风格算法的一个强大工具,特别适合需要处理各种容器和数据结构的场景。
更多关于golang实现C++ STL迭代器与算法功能的插件库iter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现C++ STL迭代器与算法功能的插件库iter的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 实现类似 C++ STL 迭代器与算法的插件库 iter
在 Golang 中实现类似 C++ STL 的迭代器和算法功能,可以使用 github.com/disksing/iter
这个库。下面我将详细介绍如何使用这个库来实现类似 C++ STL 的功能。
安装 iter 库
go get github.com/disksing/iter
基本迭代器功能
iter 库提供了类似 C++ STL 的迭代器接口和算法:
package main
import (
"fmt"
"github.com/disksing/iter"
)
func main() {
// 创建一个切片
nums := []int{1, 2, 3, 4, 5}
// 获取开始和结束迭代器
begin := iter.SliceBegin(nums)
end := iter.SliceEnd(nums)
// 使用迭代器遍历
for it := begin; !it.Equal(end); it = it.Next() {
fmt.Print(it.Get(), " ")
}
// 输出: 1 2 3 4 5
}
常用算法实现
1. 排序算法
func main() {
nums := []int{5, 3, 1, 4, 2}
begin := iter.SliceBegin(nums)
end := iter.SliceEnd(nums)
// 排序
iter.Sort(begin, end, iter.Less[int])
fmt.Println(nums) // [1 2 3 4 5]
// 自定义排序
iter.Sort(begin, end, func(a, b int) bool {
return a > b // 降序
})
fmt.Println(nums) // [5 4 3 2 1]
}
2. 查找算法
func main() {
nums := []int{1, 2, 3, 4, 5}
begin := iter.SliceBegin(nums)
end := iter.SliceEnd(nums)
// 查找元素
it := iter.Find(begin, end, 3)
if !it.Equal(end) {
fmt.Println("Found:", it.Get()) // Found: 3
}
// 二分查找(需要先排序)
iter.Sort(begin, end, iter.Less[int])
found := iter.BinarySearch(begin, end, 3)
fmt.Println("Binary search found:", found) // true
}
3. 变换算法
func main() {
nums := []int{1, 2, 3, 4, 5}
begin := iter.SliceBegin(nums)
end := iter.SliceEnd(nums)
// 每个元素加1
iter.ForEach(begin, end, func(x *int) {
*x += 1
})
fmt.Println(nums) // [2 3 4 5 6]
// 变换到另一个切片
squares := make([]int, len(nums))
iter.Transform(begin, end, iter.SliceBegin(squares), func(x int) int {
return x * x
})
fmt.Println(squares) // [4 9 16 25 36]
}
4. 其他常用算法
func main() {
nums := []int{1, 2, 3, 4, 5}
begin := iter.SliceBegin(nums)
end := iter.SliceEnd(nums)
// 反转
iter.Reverse(begin, end)
fmt.Println(nums) // [5 4 3 2 1]
// 累加
sum := iter.Accumulate(begin, end, 0, func(a, b int) int {
return a + b
})
fmt.Println("Sum:", sum) // 15
// 计数
count := iter.CountIf(begin, end, func(x int) bool {
return x%2 == 1 // 奇数
})
fmt.Println("Odd count:", count) // 3
}
自定义迭代器
iter 库也支持自定义迭代器:
type MyContainer struct {
data []string
}
func (c *MyContainer) Begin() iter.AdvanceIterator[string] {
return &MyIterator{container: c, pos: 0}
}
func (c *MyContainer) End() iter.AdvanceIterator[string] {
return &MyIterator{container: c, pos: len(c.data)}
}
type MyIterator struct {
container *MyContainer
pos int
}
func (it *MyIterator) Get() string {
return it.container.data[it.pos]
}
func (it *MyIterator) Set(v string) {
it.container.data[it.pos] = v
}
func (it *MyIterator) Next() iter.AdvanceIterator[string] {
return &MyIterator{container: it.container, pos: it.pos + 1}
}
func (it *MyIterator) Prev() iter.AdvanceIterator[string] {
return &MyIterator{container: it.container, pos: it.pos - 1}
}
func (it *MyIterator) Equal(other iter.AdvanceIterator[string]) bool {
o := other.(*MyIterator)
return it.pos == o.pos && it.container == o.container
}
func main() {
container := &MyContainer{data: []string{"a", "b", "c"}}
begin := container.Begin()
end := container.End()
// 使用算法
iter.ForEach(begin, end, func(s *string) {
*s = *s + "!"
})
fmt.Println(container.data) // [a! b! c!]
}
注意事项
- iter 库的性能不如原生 Go 循环,但在某些复杂算法场景下可以提供更清晰的代码
- 不是所有 C++ STL 算法都有对应实现
- 类型安全不如 C++ 模板系统强大
iter 库为 Go 开发者提供了一种类似 C++ STL 的编程范式,适合熟悉 C++ STL 的开发者使用,但在实际 Go 项目中,通常更推荐使用 Go 原生的切片和 map 操作。