golang实现C++ STL迭代器与算法功能的插件库iter的使用

Golang实现C++ STL迭代器与算法功能的插件库iter的使用

iter是一个Go语言实现的C++ STL迭代器和算法库,它提供了超过100种算法,几乎涵盖了C++17之前的所有STL算法。这个库的主要目标是减少手写循环,使代码更具表达性。

特点

  1. 非侵入式设计:iter不引入新的容器类型,而是重用Go现有的容器(如slice、string、list.List等),并通过迭代器适配它们以使用算法。

  2. 完整算法支持:包含几乎所有C++17之前的算法,如AllOf、FindIf、Accumulate、Shuffle、Sample、Partition等。

  3. 性能优化:库中的实现包含了一些不易察觉的性能优化。

安装

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]

优势

  1. 代码简洁:使用算法替代简单循环可以使代码更简洁易懂。

  2. 正确性保证:一些算法虽然不复杂,但正确实现并不容易,重用代码可以更容易保证正确性。

  3. 复杂算法:STL包含一些可能需要数小时才能正确实现的复杂算法,手动实现不切实际。

  4. 性能优化:库中的实现包含了一些性能优化,如MinmaxElement通过一次比较两个元素显著减少了比较次数。

iter库是Go中实现STL风格算法的一个强大工具,特别适合需要处理各种容器和数据结构的场景。


更多关于golang实现C++ STL迭代器与算法功能的插件库iter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于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!]
}

注意事项

  1. iter 库的性能不如原生 Go 循环,但在某些复杂算法场景下可以提供更清晰的代码
  2. 不是所有 C++ STL 算法都有对应实现
  3. 类型安全不如 C++ 模板系统强大

iter 库为 Go 开发者提供了一种类似 C++ STL 的编程范式,适合熟悉 C++ STL 的开发者使用,但在实际 Go 项目中,通常更推荐使用 Go 原生的切片和 map 操作。

回到顶部