你可以如何实现一个通用的过滤函数?

huangapple go评论96阅读模式
英文:

How can I implement a generic filter function?

问题

假设我正在用Golang实现这个用于过滤切片的函数:

func Filter(filter func(n int) bool) func(list []int) []int {
	return func(list []int) []int {
		r := make([]int, 0)
		for _, n := range list {
			if filter(n) {
				r = append(r, n)
			}
		}
		return r
	}
}

可以这样使用:

list := []int{1, 4, 3, 2, 7, 4, 9, 7}
r := Filter(func(n int) bool { return n > 3 })(list)

fmt.Println(r)

这个代码可以正常工作,但我有以下几个问题:

  1. 我是否应该使用完整的func语法而不是lambda表达式?
  2. 如果我希望Filter函数可以过滤任意类型的切片,我应该使用什么返回类型?

谢谢!

英文:

Suppose I'm implementing this function for filtering a Slice in Golang:

 func Filter(filter func(n int) bool) func(list []int) []int {
   return func(list []int) []int {
  	 r := make([]int, 0)
	 for _, n := range list {
 		 if filter(n) {
			 r = append(r, n)
		 }
   }

	 return r
 } 
}

To be used like this:

list := []int{1, 4, 3, 2, 7, 4, 9, 7}
r := Filter(func(n int) bool { return n > 3 })(list)

fmt.Println(r)

This works ok, but I have the following questions:

  1. Am I supposed to use the full func syntax instead of a lambda style expression?
  2. If I want my Filter to filter slices of ANY type, what return type should I use?

Thanks!

答案1

得分: 3

据我所知,目前还没有关于更简洁的匿名函数表示法("lambda")的提案被接受。

计划在2022年初发布Go 1.18时引入类型参数(也称为泛型)。届时,您将能够编写下面的程序(playground)。

如果您可以等到那个时候,建议您等待。无论如何,通常不鼓励使用reflect在代码中大量使用空的interface{}和类型断言。在Go 1.18之前的一个可行的替代方案是使用go generate来生成所需的不同特化版本(例如intstring等)。

package main

import "fmt"

func Filter[T any](filter func(n T) bool) func(T []T) []T {
    return func(list []T) []T {
        r := make([]T, 0, len(list))
        for _, n := range list {
            if filter(n) {
                r = append(r, n)
            }
        }
        return r
    }
}

func main() {
    list := []int{1, 4, 3, 2, 7, 4, 9, 7}
    r := Filter(func(n int) bool { return n > 3 })(list)
    fmt.Println(r)

    list2 := []string{"foo", "bar", "baz", "qux", "quux"}
    r2 := Filter(func(s string) bool { return len(s) <= 3 })(list2)
    fmt.Println(r2)
}
英文:
  1. As far as I know, no proposal for a more concise anonymous-function notation ("lambda") has been accepted yet.

  2. The addition of type parameters (a.k.a. generics) to the language is planned for early 2022 with the release of Go 1.18. Then, you'll be able to write the program below (playground).

    If you can wait until then, do. At any rate, using the reflect package and peppering one's code with the empty interface{} and type assertions are generally discouraged. One viable alternative until Go 1.18 would be to use go generate to generate the different specializations (for int, string, etc.) you need.

    <!-- languageL go -->

    package main
    
    import &quot;fmt&quot;
    
    func Filter[T any](filter func(n T) bool) func(T []T) []T {
        return func(list []T) []T {
            r := make([]T, 0, len(list))
            for _, n := range list {
                if filter(n) {
                    r = append(r, n)
                }
            }
            return r
        }
    }
    
    func main() {
        list := []int{1, 4, 3, 2, 7, 4, 9, 7}
        r := Filter(func(n int) bool { return n &gt; 3 })(list)
        fmt.Println(r)
    
        list2 := []string{&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;, &quot;qux&quot;, &quot;quux&quot;}
        r2 := Filter(func(s string) bool { return len(s) &lt;= 3 })(list2)
        fmt.Println(r2)
    }
    

huangapple
  • 本文由 发表于 2021年5月27日 12:37:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/67715761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定