Suppose I would like to apply a function to every element in a list, and then put the resulting values in another list so I can immediately use them. In python, I would do something like this:
list = [1,2,3] str = ', '.join(multiply(x, 2) for x in list) In Go, I do something like this:
list := []int{1,2,3} list2 := []int for _,x := range list { list2 := append(list2, multiply(x, 2)) } str := strings.Join(list2, ", ") Is it possible to do this in a shorter way?
35 Answers
I would do exactly as you did, with a few tweaks to fix typos
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) } This is an old question, but was the top hit in my Google search, and I found information that I believe will be helpful to the OP and anyone else who arrives here, looking for the same thing.
There is a shorter way, although you have to write the map function yourself.
In go, func is a type, which allows you to write a function that accepts as input the subject slice and a function, and which iterates over that slice, applying that function.
See the Map function near the bottom of this Go by Example page :
I've included it here for reference:
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 } You then call it like so:
fmt.Println(Map(strs, strings.ToUpper)) So, yes: The shorter way you are looking for exists, although it is not built into the language itself.
3I've created a small utility package with Mapand Filter methods now that generics have been introduced in 1.18 :)
Example usage
package main import ( "fmt" sf "" ) 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) } Found a way to define a generic map array function
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}) 2With go1.18+ you can write a much cleaner generic Map function:
func Map[T, V any](ts []T, fn func(T) V) []V { result := make([]V, len(ts)) for i, t := range ts { result[i] = fn(t) } return result } Usage, e.g:
input := []int{4, 5, 3} outputInts := Map(input, func(item int) int { return item + 1 }) outputStrings := Map(input, func(item int) string { return fmt.Sprintf("Item:%d", item) }) 0