英文:
Writing a nested iterator of depth d
问题
如何实现一个带有深度参数的嵌套迭代器。当深度为1时,它就是一个简单的迭代器,类似于简单的for循环。
func Iter(depth int) chan string {
ch := make(chan string)
go func() {
if depth == 1 {
for i := 1; i < 60; i++ {
ch <- fmt.Sprintf("%d", i)
}
} else {
subIter := Iter(depth - 1)
for i := 1; i < 60; i++ {
for sub := range subIter {
ch <- fmt.Sprintf("%s,%d", sub, i)
}
subIter = Iter(depth - 1)
}
}
close(ch)
}()
return ch
}
输出为1,2,3...59
当深度为2时,输出为"1,1" "1,2" ... "1,59" "2,1" ... "59,59"
当深度为3时,输出为"1,1,1" ... "59,59,59"
这样可以避免使用嵌套的for循环。
英文:
How to realize a nested iterator that takes a depth argument. A simple iterator would be when depth = 1. it is a simple iterator which runs like a simple for loop.
func Iter () chan int {
ch := make(chan int);
go func () {
for i := 1; i < 60; i++ {
ch <- i
}
close(ch)
} ();
return ch
}
Output is 1,2,3...59
For depth = 2 Output would be "1,1" "1,2" ... "1,59" "2,1" ... "59,59"
For depth = 3 Output would be "1,1,1" ... "59,59,59
"
I want to avoid a nested for loop. What is the solution here ?
答案1
得分: 2
我不知道是否可以避免嵌套循环,但是一种解决方案是使用管道的流水线。例如:
const ITER_N = 60
// ----------------
func _goFunc1(out chan string) {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%d", i)
}
close(out)
}
func _goFuncN(in chan string, out chan string) {
for j := range in {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%s,%d", j, i)
}
}
close(out)
}
// ----------------
// 创建流水线
func IterDepth(d int) chan string {
c1 := make(chan string)
go _goFunc1(c1)
var c2 chan string
for ; d > 1; d-- {
c2 = make(chan string)
go _goFuncN(c1, c2)
c1 = c2
}
return c1
}
func main() {
c := IterDepth(2)
for i := range c {
fmt.Println(i)
}
}
你可以使用以下代码进行测试:
func main() {
c := IterDepth(2)
for i := range c {
fmt.Println(i)
}
}
英文:
I don't know if it is possible to avoid nested loops, but one solution is to use a pipeline of channels. For example:
const ITER_N = 60
// ----------------
func _goFunc1(out chan string) {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%d", i)
}
close(out)
}
func _goFuncN(in chan string, out chan string) {
for j := range in {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%s,%d", j, i)
}
}
close(out)
}
// ----------------
// create the pipeline
func IterDepth(d int) chan string {
c1 := make(chan string)
go _goFunc1(c1)
var c2 chan string
for ; d > 1; d-- {
c2 = make(chan string)
go _goFuncN(c1, c2)
c1 = c2
}
return c1
}
You can test it with:
func main() {
c := IterDepth(2)
for i := range c {
fmt.Println(i)
}
}
答案2
得分: 1
我通常使用闭包来实现迭代器。多个维度并不会使问题变得更加困难。以下是一个示例,展示如何实现迭代器:
package main
import "fmt"
func iter(min, max, depth int) func() ([]int, bool) {
s := make([]int, depth)
for i := range s {
s[i] = min
}
s[0] = min - 1
return func() ([]int, bool) {
s[0]++
for i := 0; i < depth-1; i++ {
if s[i] >= max {
s[i] = min
s[i+1]++
}
}
if s[depth-1] >= max {
return nil, false
}
return s, true
}
}
func main() {
// 三个维度,范围在[1,4)
i := iter(1, 4, 3)
for s, ok := i(); ok; s, ok = i() {
fmt.Println(s)
}
}
你可以在Playground上尝试运行它。
例如,如果需要的话,可以简单地将参数作为一个整数切片传递,这样你就可以为每个维度设置不同的限制。
英文:
I usually implement iterators using closures. Multiple dimensions don't make the problem much harder. Here's one example of how to do this:
package main
import "fmt"
func iter(min, max, depth int) func() ([]int, bool) {
s := make([]int, depth)
for i := range s {
s[i] = min
}
s[0] = min - 1
return func() ([]int, bool) {
s[0]++
for i := 0; i < depth-1; i++ {
if s[i] >= max {
s[i] = min
s[i+1]++
}
}
if s[depth-1] >= max {
return nil, false
}
return s, true
}
}
func main() {
// Three dimensions, ranging between [1,4)
i := iter(1, 4, 3)
for s, ok := i(); ok; s, ok = i() {
fmt.Println(s)
}
}
Try it out on the Playground.
It'd be a simple change for example to give arguments as a single int slice instead, so that you could have per-dimension limits, if such a thing were necessary.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论