切片
Slicing a slice
问题描述:
我有一片 bar
。如果 bar
中至少有 2 个元素,我想用 bar 的前两个元素创建另一个切片 foo
。或者如果 bar
至少有一个元素,则使用 bar
的第一个元素。
我的想法:
// bar := []int{1, 2, 3...
foo := bar[:(int)(math.Min(float64(len(bar)), 2))]
编辑:
这是我尝试过的另一种方法,
x := 2
if len(bar) < 2 {
x = len(bar)
}
foo := bar[:x]
是否可以改进代码?至少,投两次来实现如此简单的事情对我来说并不好看。
只需使用一个 if
。它更具可读性和性能,因为 int
和 float64
.
之间没有转换
var foo []int
if len(bar) > 1 {
foo = bar[:2]
} else {
foo = bar[:len(bar)]
}
Go 没有 math.MinInt
。但是实现一个很简单:
func Min(x, y int) int {
if x < y {
return x
}
return y
}
...
foo := bar[:Min(len(bar), 2)]
bar := []int{}
n := len(bar)
if n > 2 {
n = 2
}
foo := bar[:n]
fmt.Printf("%v", foo)
适用于 len(bar) = 0, 1, 2, n.. Playground sample
任意数量元素的通用(如您在评论中所问)函数:
func strip(s []int, n int) []int {
if len(s) < n {
n = len(s)
}
return s[:n]
}
...
foo := strip(bar, 2)
如果切片的长度大于 2,您可以重新切片。如果不是,无需重新切片,只需在赋值中使用切片本身,这将自动满足您的需求:结果最多包含 2 个元素。
您甚至可以 "spare" if
的 else
分支:
foo := bar
if len(foo) > 2 {
foo = foo[:2]
}
注:
切片是引用类型。因此,即使您使用 bar
初始化 foo
,如果您之后修改 foo
变量 (不是切片的元素),那确实不影响bar
(赋值时复制参考值):
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]
输出(在 Go Playground 上尝试):
[0 1]
[0 1 2 3]
问题描述:
我有一片 bar
。如果 bar
中至少有 2 个元素,我想用 bar 的前两个元素创建另一个切片 foo
。或者如果 bar
至少有一个元素,则使用 bar
的第一个元素。
我的想法:
// bar := []int{1, 2, 3...
foo := bar[:(int)(math.Min(float64(len(bar)), 2))]
编辑: 这是我尝试过的另一种方法,
x := 2
if len(bar) < 2 {
x = len(bar)
}
foo := bar[:x]
是否可以改进代码?至少,投两次来实现如此简单的事情对我来说并不好看。
只需使用一个 if
。它更具可读性和性能,因为 int
和 float64
.
var foo []int
if len(bar) > 1 {
foo = bar[:2]
} else {
foo = bar[:len(bar)]
}
Go 没有 math.MinInt
。但是实现一个很简单:
func Min(x, y int) int {
if x < y {
return x
}
return y
}
...
foo := bar[:Min(len(bar), 2)]
bar := []int{}
n := len(bar)
if n > 2 {
n = 2
}
foo := bar[:n]
fmt.Printf("%v", foo)
适用于 len(bar) = 0, 1, 2, n.. Playground sample
任意数量元素的通用(如您在评论中所问)函数:
func strip(s []int, n int) []int {
if len(s) < n {
n = len(s)
}
return s[:n]
}
...
foo := strip(bar, 2)
如果切片的长度大于 2,您可以重新切片。如果不是,无需重新切片,只需在赋值中使用切片本身,这将自动满足您的需求:结果最多包含 2 个元素。
您甚至可以 "spare" if
的 else
分支:
foo := bar
if len(foo) > 2 {
foo = foo[:2]
}
注:
切片是引用类型。因此,即使您使用 bar
初始化 foo
,如果您之后修改 foo
变量 (不是切片的元素),那确实不影响bar
(赋值时复制参考值):
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]
输出(在 Go Playground 上尝试):
[0 1]
[0 1 2 3]