Skip to content

Proposal: add generic Filter to slices package #58014

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
karelbilek opened this issue Jan 26, 2023 · 5 comments
Closed

Proposal: add generic Filter to slices package #58014

karelbilek opened this issue Jan 26, 2023 · 5 comments

Comments

@karelbilek
Copy link

karelbilek commented Jan 26, 2023

A filter-like function would be useful in Slices package. It is not hard to write manually, but why not to have it in exp/slices (or even in built-in slices package).

This is a first, fizzbuzz-level code, draft, based on what I used locally; there might be a more optimised version.

func Filter[E any](s []E, f func(E) bool) []E {
    s2 := make([]E, 0, len(s))
    for _, e := range s {
        if f(e) {
             s2 = append(s2, e)
        }
    }
    return s2
}

(What I use locally is actually FilterWithError, with signature func FilterWithError[E any](s []E, f func(E) (bool, err)) ([]E, err)), but I think it would not fit into slices package as it is currently.)

When I asked on slack, it was recommended me to name it Select/Reject, to make more clear if filter is positive or negative. I think using "filter" is fine, as it is common in other languages and quite clear; Select means something else in Go so it could be confusing.

@gopherbot gopherbot added this to the Proposal milestone Jan 26, 2023
@robpike
Copy link
Contributor

robpike commented Jan 26, 2023

You can just use a for loop, which is more flexible in general. I am not being facetious; the filter operation tends to obscure allocation and overhead, and also tends to be overused. Although I may be in the minority, I do not believe this would be a wise addition to the standard library.

@seankhliao
Copy link
Member

these were explicitly removed, see #47203 (comment)

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Jan 26, 2023
@karelbilek
Copy link
Author

@robpike That makes sense; we are having them in a business layer where the extra overhead is negligent compared with other tasks, but it's true it might be different on lower layers

@seankhliao ah ok. Thanks for pointing me in the right direction though.

@DeedleFake
Copy link

@4cq2

Go 1.21 adds slices.DeleteFunc(), which is essentially an in-place filter operation, so there's no need to copy and paste the internal implementation.

@ghost
Copy link

ghost commented Jun 3, 2023

note the previous comment is misleading, as DeleteFunc does not return a copy, it edits the slice in place, which in some cases is not going to be what the user wants. here is actual filter that returns a copy:

https://github.com/golang/go/blob/go1.20.4/src/internal/types/testdata/check/slices.go

or, you could combine DeleteFunc with Clone:

https://pkg.go.dev/slices@master#Clone

also here is a function to invert a selection:

func Not[E any](fn func(E) bool) func(E) bool {
   return func(value E) bool {
      return !fn(value)
   }
}

@golang golang locked and limited conversation to collaborators Jun 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants