Reputation: 4565
Problem description:
I've a slice bar
. I want to create another slice foo
with the first two elements of bar if there're at least 2 elements in bar
. Or with the first element of bar
if bar
has at least one element.
The idea I had:
// bar := []int{1, 2, 3...
foo := bar[:(int)(math.Min(float64(len(bar)), 2))]
EDIT: Here's another way I tried,
x := 2
if len(bar) < 2 {
x = len(bar)
}
foo := bar[:x]
Is it possible to improve the code? At least, casting twice to achieve something so simple doesn't look good to me.
Upvotes: 5
Views: 11684
Reputation: 417512
If the length of your slice is greater than 2, you can reslice it. If not, no need to reslice just use the slice itself in assignment which will automatically satisfy your needs: result will have up to a maximum of 2 elements.
You can even "spare" the else
branch of the if
:
foo := bar
if len(foo) > 2 {
foo = foo[:2]
}
Note:
Slices are reference types. So even though you used bar
to initialize foo
, if you modify the foo
variable afterwards (not the elements of the slice), that does not affect bar
(the reference value is copied when assigned):
bar := []int{0, 1, 2, 3}
foo := bar
if len(foo) > 2 {
foo = foo[:2]
}
fmt.Println(foo) // Here foo is [0, 1] as expected
foo = foo[:1] // Reslicing foo
fmt.Println(bar) // Bar is unaffected, bar = [0 1 2 3]
Output (try it on the Go Playground):
[0 1]
[0 1 2 3]
Upvotes: 9
Reputation: 6723
General (as you ask in a comment) function for arbitrary number of elements:
func strip(s []int, n int) []int {
if len(s) < n {
n = len(s)
}
return s[:n]
}
...
foo := strip(bar, 2)
Upvotes: 0
Reputation: 6864
bar := []int{}
n := len(bar)
if n > 2 {
n = 2
}
foo := bar[:n]
fmt.Printf("%v", foo)
Works with len(bar) = 0, 1, 2, n.. Playground sample
Upvotes: 0
Reputation: 36189
Just use an if
. It's much more readable and performant, since there is no conversion between int
and float64
.
var foo []int
if len(bar) > 1 {
foo = bar[:2]
} else {
foo = bar[:len(bar)]
}
Upvotes: 4
Reputation: 77945
Go does not have a math.MinInt
. But implementing one is as simple as:
func Min(x, y int) int {
if x < y {
return x
}
return y
}
...
foo := bar[:Min(len(bar), 2)]
Upvotes: 1