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?

3

5 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.

3

I'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}) 
2

With 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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy