获取一个整数的第一个数字

huangapple go评论87阅读模式
英文:

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] &lt; 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 &gt;= 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.

Full playground example, courtesy of Rayfen.

答案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] &lt; 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 &quot;sort&quot;
import &quot;fmt&quot;
import &quot;math&quot;

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] ) &lt; 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

huangapple
  • 本文由 发表于 2017年8月12日 00:51:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/45640144.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定