【问题标题】:Short way to apply a function to all elements in a list in golang将函数应用于golang列表中所有元素的快捷方式
【发布时间】:2015-11-16 00:14:26
【问题描述】:

假设我想将一个函数应用于列表中的每个元素,然后将结果值放入另一个列表中,以便我可以立即使用它们。在 python 中,我会做这样的事情:

list = [1,2,3]
str = ', '.join(multiply(x, 2) for x in list)

在 Go 中,我会这样做:

list := []int{1,2,3}
list2 := []int

for _,x := range list {
    list2 := append(list2, multiply(x, 2))
}

str := strings.Join(list2, ", ")

是否有可能以更短的方式做到这一点?

【问题讨论】:

  • 您正在寻找的是map 函数。 (与类似于 Python 的 dictmap 数据类型相反)
  • 谢谢亚当,知道在哪里可以找到它们吗?它是标准库的一部分吗?我找不到太多关于它的信息......
  • 我提出了一个答案,但谷歌搜索“golang map function”会给你更多信息。简短的回答是不,golang 中没有这样的功能

标签: go


【解决方案1】:

这是一个老问题,但在我的 Google 搜索中是热门问题,我发现我认为对 OP 和其他任何到达这里并寻找相同内容的人都有帮助的信息。

有一个更短的方法,虽然你必须自己编写地图函数。

在 go 中,func 是一种类型,它允许您编写一个函数,该函数接受主题切片和一个函数作为输入,并在该切片上进行迭代,应用该函数。

请参阅此 Go by Example 页面底部附近的 Map 函数:https://gobyexample.com/collection-functions

我已将其包含在此处以供参考:

func Map(vs []string, f func(string) string) []string {
    vsm := make([]string, len(vs))
    for i, v := range vs {
        vsm[i] = f(v)
    }
    return vsm
}

然后你可以这样称呼它:

fmt.Println(Map(strs, strings.ToUpper))

所以,是的:您正在寻找的更短的方式是存在的,尽管它没有内置在语言本身中。

【讨论】:

  • 它没有内置的原因是 Go 没有泛型(还没有?)。所以你必须为每种类型编写不同的 Map。
  • 看了上面的评论后,我想知道反射,接口是否可以使用,然后我在下面找到了答案。超现实。
  • @Anubhav :请注意,interface 与“通用”不同,因为它通常在编程语言中表示;另一个答案的Map() 函数的结果与输入的类型不同,这可能适合也可能不适合特定情况;是的,interface 在某些方面可以像其他类型一样对待,但不是在所有方面,所以请牢记这一点,使用基于interfaceMap()
【解决方案2】:

我已经创建了一个带有 MapFilter 方法的小型实用程序包,因为泛型已在 1.18 中引入 :)

https://pkg.go.dev/github.com/sa-/slicefunk

示例用法

package main

import (
    "fmt"

    sf "github.com/sa-/slicefunk"
)

func main() {
    original := []int{1, 2, 3, 4, 5}
    newArray := sf.Map(original, func(item int) int { return item + 1 })
    newArray = sf.Map(newArray, func(item int) int { return item * 3 })
    newArray = sf.Filter(newArray, func(item int) bool { return item%2 == 0 })
    fmt.Println(newArray)
}

【讨论】:

    【解决方案3】:

    我会按照你的做法做,只是稍微调整一下以修复错别字

    import (
        "fmt"
        "strconv"
        "strings"
    )
    
    func main() {
        list := []int{1,2,3}
    
        var list2 []string
        for _, x := range list {
            list2 = append(list2, strconv.Itoa(x * 2))  // note the = instead of :=
        }
    
        str := strings.Join(list2, ", ")
        fmt.Println(str)
    }
    

    【讨论】:

      【解决方案4】:

      找到了一种定义通用地图数组函数的方法

      func Map(t interface{}, f func(interface{}) interface{} ) []interface{} {
          switch reflect.TypeOf(t).Kind() {
          case reflect.Slice:
              s := reflect.ValueOf(t)
              arr := make([]interface{}, s.Len())
              for i := 0; i < s.Len(); i++ {
                  arr[i] = f(s.Index(i).Interface())
              }
              return arr
          }
          return nil
      }
      
      origin := []int{4,5,3}
      newArray := Map(origin, func(item interface{}) interface{} { return item.(int) + 1})
      

      【讨论】:

      • 这有点简洁。在 go 中使用两个高级概念,即 interface{}reflect 解释应该是最受欢迎的。我想你“找到”了 out 怎么做,而不是“找到”它在某处并复制了它
      • 看了上面的答案后,我想到了使用反射和接口,以及反射如何减慢它,向下滚动一点,看看。
      猜你喜欢
      • 2013-08-15
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 2017-09-03
      • 1970-01-01
      • 2014-08-19
      • 1970-01-01
      相关资源
      最近更新 更多