Skip to content

proposal: slices: Add functions Map and Filter #68065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1nv8rzim opened this issue Jun 19, 2024 · 3 comments
Closed

proposal: slices: Add functions Map and Filter #68065

1nv8rzim opened this issue Jun 19, 2024 · 3 comments
Labels
Milestone

Comments

@1nv8rzim
Copy link

Proposal Details

I propose the creation of two new function, Map and Filter, to the slices package:

Map

Map creates a new slice containing the results of running all indices of a slice through a provided functions

func Map[S ~[]E, E, R any](slice S, mapper func(int, E) R) []R

Example:

// Square all integers in a slice
slices.Map(
    []int{1, 2, 3, 4},
    func(i, v int) int {
        return v * v
    },
)
// Output: [1 4 9 16]

Filter

Filter create a new slice containing a subset of indices of an existing slice based on running all indices through a provided filter function

func Filter[S ~[]E, E any](slice S, filter func(int, E) bool) []E

Example:

// Filter out all odd numbers in a slice
slices.Filter(
    []int{1, 2, 3, 4},
    func(i, v int) bool {
        return v%2 == 0
    },
)
// Output: [2 4]

Reasoning

Personally I find myself creating these exact function in most of my projects and they help a ton with writing clean code.

It allows me to change from code like this:

existingSlice := []int{1, 2, 3, 4}

filterSlice := make([]int, 0, len(existingSlice))
for _, v := range existingSlice {
    if v%2 == 0 {
        filterSlice = append(filterSlice, v)
    }
}

mappedSlice := make([]string, len(filterSlice))
for i, v := range filterSlice {
    mappedSlice[i] = strconv.Itoa(v)
}

and simplify it something like this:

existingSlice := []int{1, 2, 3, 4}

filterSlice := slice.Filter(existingSlice, func(i, v int) bool { return v%2 == 0 })
mappedSlice := slice.Map(filterSlice, func(i, v int) string { return strconv.Itoa(v) })

** Also note: this is super useful for doing inline operation

Implementation

New time contributor here, so I did not know that proposals were needed before making API change. I already have proposed implementation using the patterns that the slices packages uses:

// Map returns a new slice containing the result of applying the mapper function to each element of the provided.
// The result has the same length as the input slice.
// The result is never nil.
// The result will be in the same order as the input slice.
// The mapper function must not modify the elements of the input slice.
func Map[S ~[]E, E, R any](slice S, mapper func(int, E) R) []R {
	mappedSlice := make([]R, len(slice))
	for i, v := range slice {
		mappedSlice[i] = mapper(i, v)
	}
	return mappedSlice
}

// Filter returns a new slice containing only the elements of the provided slice for which the filter function returns true.
// The result has length <= len(slice).
// The result is never nil.
// The result will be in the same order as the input slice.
// The filter function must not modify the elements of the input slice.
func Filter[S ~[]E, E any](slice S, filter func(int, E) bool) []E {
	filteredSlice := make([]E, 0, len(slice))
	for i, v := range slice {
		if filter(i, v) {
			filteredSlice = append(filteredSlice, v)
		}
	}
	return Clip(filteredSlice)
}
@gopherbot gopherbot added this to the Proposal milestone Jun 19, 2024
@1nv8rzim
Copy link
Author

Reading through the similar issues, all of the similar proposals have been closed and they seem to point to #47203 (comment) as the reason to why.

  • Deleted Map, Filter, Reduce (probably better as part of a more comprehensive streams API somewhere else)

Reasoning to why these haven't been implemented is in anticipation of this "streams API" which I would assume would refer to the iter package: #61899. Likewise, slices seems to be getting these iterator functions as recent as a month ago: https://go-review.googlesource.com/c/go/+/568477.

However, it seems as though functions like Map and Filter might have fallen through the cracks?

@ianlancetaylor
Copy link
Contributor

This is #61898. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants