英文:
Getting the first digit of an int
问题
如何按每个整数的第一个数字对整数切片进行排序?
我正在尝试编写自己的自定义排序:
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
return s[i]/10 < s[j]/10
}
但是我得到了这个错误:
s[j][0](类型int不支持索引)
英文:
How do I sort a slice of ints by the first digit of each int?
I am trying to write my own custom sort:
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
return s[i][0] < s[j][0]
}
But I get this error:
> s[j][0] (type int does not support indexing)
答案1
得分: 7
@RayfenWindspear提供了最易于使用和阅读的答案,并且对性能影响的问题是正确的。如果性能比可维护性更重要,你可以使用迭代除法来获取最高位的十进制数字:
var i int
for i = n; i >= 10; i = i / 10 {}
// i == 最高位数字
请注意,你必须在循环外部声明i
,以便在循环找到最高位数字后能够使用它。我还建议使用你自己的数据集对两种方法进行基准测试,以了解在你特定的情况下实际的性能影响是什么。
完整的 playground 示例,由 Rayfen 提供。
英文:
@RayfenWindspear has the easiest to use and read answer, but is correct about the performance hit. If performance is more important than maintainability, you can do the same thing using iterative division to get the most-significant base-10 digit:
var i int
for i = n; i >= 10; i = i / 10 {}
// i == most significant digit
Note that you have to declare i
outside the loop to be able to use it after the loop finds the most-significant digit. I'd also benchmark both with your own data set to see what the real performance impact is in your particular situation.
答案2
得分: 1
你可以在排序函数中将它们转换为字符串,然后索引第一个字符。对于[]int
类型,你可以使用https://godoc.org/strconv#Itoa。不幸的是,这种方法会导致字符串转换的性能损失。
以下是代码的翻译:
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
si := strconv.Itoa(s[i])
sj := strconv.Itoa(s[j])
return si[0] < sj[0]
}
你可以在这里查看代码:https://play.golang.org/p/S4j3NlfinD
英文:
You could convert them to strings in your sort function then index the first character. For []int
you can use https://godoc.org/strconv#Itoa . Unfortunately this method will take a huge performance hit for the string conversion.
https://play.golang.org/p/S4j3NlfinD
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
si := strconv.Itoa(s[i])
sj := strconv.Itoa(s[j])
return si[0] < sj[0]
}
答案3
得分: 0
如果你需要一个包含许多高级数学函数的解决方案,可能性能好也可能性能不好:
package main
import "sort"
import "fmt"
import "math"
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
return firstDigit(s[i]) < firstDigit(s[j])
}
func firstDigit(x int) int {
return int(math.Abs(float64(x)) / math.Pow(10, float64(numDigits(x)-1)))
}
func numDigits(x int) int {
if x == 0 {
return 1
}
return int(math.Floor(math.Log10(math.Abs(float64(x))))) + 1
}
func main() {
ints := []int{3, 20, 400, -500, 101}
sort.Sort(ByFirstDigit(ints))
fmt.Println(ints)
}
这是一个playground链接(相同的代码):
https://play.golang.org/p/uLyBMlra2N
英文:
In case you want a solution with a lot of high-level math functions that may or may not perform well:
package main
import "sort"
import "fmt"
import "math"
type ByFirstDigit []int
func (s ByFirstDigit) Len() int {
return len(s)
}
func (s ByFirstDigit) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByFirstDigit) Less(i, j int) bool {
return firstDigit( s[i] ) < firstDigit( s[j] )
}
func firstDigit( x int ) int {
return int( math.Abs( float64( x ) ) / math.Pow( 10, float64( numDigits(x) - 1 ) ) )
}
func numDigits( x int ) int {
if ( x == 0 ) { return 1 }
return int( math.Floor( math.Log10( math.Abs( float64(x) ) ) ) ) + 1
}
func main() {
ints := []int{3, 20, 400, -500, 101}
sort.Sort( ByFirstDigit( ints ) )
fmt.Println( ints )
}
Here's a playground (same code):
https://play.golang.org/p/uLyBMlra2N
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论