-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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
proposal: slices: add Cut, CutPrefix and CutSuffix #64095
Comments
Lightly tested prototypes: func Cut[S ~[]E, E comparable](s S, prefix ...E) (before, after S, found bool) {
if len(prefix) == 0 {
return s[:0], s, true
}
if len(prefix) <= len(s) {
i:
for i := range s[:len(s)-len(prefix)+1] {
for j, x := range prefix {
if s[i+j] != x {
continue i
}
}
return s[:i], s[i+len(prefix):], true
}
}
return s, nil, false
}
func CutPrefix[S ~[]E, E comparable](s S, prefix ...E) (after S, found bool) {
if len(prefix) == 0 {
return s, true
}
if len(prefix) > len(s) {
return s, false
}
for j, x := range prefix {
if s[j] != x {
return s, false
}
}
return s[len(prefix):], true
}
func CutSuffix[S ~[]E, E comparable](s S, suffix ...E) (before S, found bool) {
if len(suffix) == 0 {
return s, true
}
if len(suffix) > len(s) {
return s, false
}
i := len(s) - len(suffix)
for j, x := range suffix {
if s[i+j] != x {
return s, false
}
}
return s[:i], true
}
func main() {
fmt.Println(Cut(strings.Fields("a b c")))
fmt.Println(Cut(strings.Fields("a b c"), "a"))
fmt.Println(Cut(strings.Fields("a b c"), "b"))
fmt.Println(Cut(strings.Fields("a b c"), "c"))
fmt.Println(Cut(strings.Fields("a b c"), "a", "b"))
fmt.Println(Cut(strings.Fields("a b c"), "b", "c"))
fmt.Println(Cut(strings.Fields("a b c"), "a", "b", "c"))
fmt.Println(Cut(strings.Fields("a b c"), "a", "b", "c", "d"))
fmt.Println(Cut(strings.Fields("a b c"), "x"))
fmt.Println()
fmt.Println(CutPrefix(strings.Fields("a b c")))
fmt.Println(CutPrefix(strings.Fields("a b c"), "a"))
fmt.Println(CutPrefix(strings.Fields("a b c"), "a", "b"))
fmt.Println(CutPrefix(strings.Fields("a b c"), "a", "b", "c"))
fmt.Println(CutPrefix(strings.Fields("a b c"), "a", "b", "c", "d"))
fmt.Println(CutPrefix(strings.Fields("a b c"), "x"))
fmt.Println()
fmt.Println(CutSuffix(strings.Fields("a b c")))
fmt.Println(CutSuffix(strings.Fields("a b c"), "c"))
fmt.Println(CutSuffix(strings.Fields("a b c"), "b", "c"))
fmt.Println(CutSuffix(strings.Fields("a b c"), "a", "b", "c"))
fmt.Println(CutSuffix(strings.Fields("a b c"), "x", "a", "b", "c"))
fmt.Println(CutSuffix(strings.Fields("a b c"), "x"))
} |
Should this also include Func variants? Just as we do with other functions in the slices package. func CutFunc[S ~[]E, E any](s S, sep ...E, eq func(E, E) bool) (before, after S, found bool)
func CutPrefixFunc[S ~[]E, E any](s S, prefix ...E, eq func(E, E) bool) (after S, found bool)
func CutSuffixFunc[S ~[]E, E any](s S, suffix ...E, eq func(E, E) bool) (before S, found bool) |
Is this a common to have slices with inline separator elements? |
I use this sort of method frequently when writing simple parsers, especially those involving whitespace-delimited formats. For instance, you'd iterate over lines with This sort of function would also ease checking for and removing a prefix or suffix from an arbitrary slice without needing to add error-prone length checks everywhere. |
Making it variadic is asymmetric with string.Cut and friends, and raises a momentary confusion (resolved by the types) about whether the function accepts a single prefix expressed as sequence of elements, or a set of possible prefixes. It would be clearer, while no less efficient, for the caller to construct the slice. The design seems reasonable but I don't immediately recall many times that I've needed this function, perhaps because repeatedly searching for subslices feels like a sign that I'm using the wrong algorithm. (Substrings are different because they enjoy such highly optimized hardware and search algorithms.) |
The strings and bytes packages have Cut, CutPrefix, and CutSuffix.
I propose adding the following functions to the slices package:
For ergonomics, I chose to make sep/prefix/suffix variadic, since most uses I can think of (e.g., simple parsers) would generally have one, or a few elements at most.
The text was updated successfully, but these errors were encountered: