使用闭包在Go中编写下一个Permutation,我的代码出了什么问题

问题描述 投票:-1回答:2

我编写了一个使用闭包的函数“iterPermutation”。我想从闭包中返回数组和布尔值,这是我无法做到的。所以只尝试了数组,但它仍然给出错误

不能在返回参数中使用func literal(类型为func()[] int)作为type [] int

我想用iterPermutation之类的

a := []int{0,1,2,3,4}
nextPermutation, exists := iterPermutation(a)
for exists {
    nextPermutation()
}

func iterPermutation(a []int) []int {
    return func() []int {
        i := len(a) - 2

        for i >= 0 && a[i+1] <= a[i] {
            i--
        }
        if i < 0 {
            return a
        }

        j := len(a) - 1
        for j >= 0 && a[j] <= a[i] {
            j--
        }

        a[i], a[j] = a[j], a[i]

        for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
            a[k], a[l] = a[l], a[k]
        }
        return a
    }
}
go
2个回答
0
投票

对于Return statements Golang规格描述:

返回值可以在“return”语句中明确列出。每个表达式必须是单值的,并且可以赋值给函数结果类型的相应元素。

调用permutation的函数应该包含两个值,一个用于数组,另一个用于布尔值。由于您从函数返回中分配了两个变量:

a := []int{0,1,2,3,4}
nextPermutation, exists := iterPermutation(a) // it should return two values one for nextPermutation which is an array and other is exists which might be a boolean value.
for exists {
    nextPermutation()
}

对于以下错误:

“不能使用func literal(类型为func()[] int)作为返回参数的类型[] int”

你返回func()文字包含在置换的闭包函数内以及布尔值,因此将返回类型更改为:

package main

func main(){
    a := []int{0,1,2,3,4}
    nextPermutation, _ := iterPermutation(a)
        nextPermutation()
}

func iterPermutation(a []int) ((func() []int), bool) { // return both values
    return func() []int {
        i := len(a) - 2

        for i >= 0 && a[i+1] <= a[i] {
            i--
        }
        if i < 0 {
            return a
        }

        j := len(a) - 1
        for j >= 0 && a[j] <= a[i] {
            j--
        }

        a[i], a[j] = a[j], a[i]

        for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
            a[k], a[l] = a[l], a[k]
        }
        return a
    }, true // add boolean value to return from the function.
}

关于Playground的工作答案


0
投票

我将忽略你的闭包中的“置换”逻辑,并专注于你需要注意的几个概念,这样它就像你计划用你的代码一样工作。如果我错了,请纠正我,但是你想从关闭中获取一系列项目,直到exists为假,对吧?

首先,要正确编译nextPermutation, exists := iterPermutation(a)iterPermutation需要返回两个值,如下所示:

func iterPermutation(a []int) (func() []int, bool) {
   exists := true
   return func() []int {
      //rest of your code
      if i < 0 {
        exists = false
        return a
      }
      //rest of your code
   }, exists
} 

您面临的下一个问题是,使用上述方法,您将获得exists值。由于您要返回exists的值,因此对exists的任何更改都不会超出iterPermutation的范围。您可以通过返回指针来解决此问题。这是实现它的一种方式:

a := []int{0,1,2,3,4}
nextPermutation, check := iterPermutation(a)

while check.Exists {
   nextPermutation()
}

type Check struct {
    Exists bool 
}

func iterPermutation(a []int) (func() []int, *Check) {
check:= &Check{
          Exists: true,
}   
return func() []int {
        i := len(a) - 2

        for i >= 0 && a[i+1] <= a[i] {
            i--
        }
        if i < 0 {
        check.Exists = false //this is put here as an example
            return a
        }

        j := len(a) - 1
        for j >= 0 && a[j] <= a[i] {
            j--
        }

        a[i], a[j] = a[j], a[i]

        for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
            a[k], a[l] = a[l], a[k]
        }
        return a
    }, check
}

当您返回Check类型的指针时,iterPermutation或闭包中的任何更改都会在这些之外可见,因为您正在访问内存引用。

© www.soinside.com 2019 - 2024. All rights reserved.