2017-08-11 45 views
4

如何按每個int的第一個數字對整片進行排序?獲取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][0] < s[j][0] 
} 

但我得到這個錯誤:

s[j][0] (type int does not support indexing)

+0

能否號碼是否定的? – Akavall

回答

5

@RayfenWindspear具有最容易使用和閱讀的答案,但對性能影響正確的。

var i int 
for i = n; i >= 10; i = i/10 {} 
// i == most significant digit 

請注意,您必須聲明i外循環才能夠使用:如果性能比維修更重要的是,你可以使用迭代劃分,以獲得最顯著基10位做同樣的事情它在循環後找到最重要的數字。我還會使用自己的數據集對兩者進行基準測試,以瞭解真實的性能影響對您的特定情況的影響。

Full playground example, courtesy of Rayfen

+0

太棒了!不知道爲什麼我沒有想到這一點。我的第一個想法是按位操作員,但很明顯這是行不通的,所以我直接找到了簡單的答案。 – RayfenWindspear

+1

我通常更喜歡簡單的答案,因爲它更清楚發生了什麼事情。然後,當實施完成時,如果性能不符合要求,基準,配置文件和優化。不成熟的優化是所有邪惡的根源:) – Adrian

+1

順便說一句,這有一個錯誤,因爲它沒有考慮數字'10'。 「10」應該是第一個值。看到這裏https://play.golang.org/p/eYZMVXQURS – RayfenWindspear

1

你可以將它們轉換爲字符串,在你的排序功能,那麼指數的第一個字符。對於[]int,您可以使用https://godoc.org/strconv#Itoa。不幸的是,這種方法會對字符串轉換造成巨大的性能影響。

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] 
} 
+0

'strconv'包具有'Append *'函數用於格式化,無需額外的字符串轉換。 – JimB

+0

@JimB但結果將是一個'[]字節',這將不得不被轉換爲字符串來使用。我不知道Append *函數會更好。 – RayfenWindspear

+0

不,你不需要將它格式化爲一個字符串來獲得第一個數字,片中的第一個「字節」是第一個數字。它的速度更快,因爲它不需要每次都分配新的字符串(在內部FormatInt格式中首先調用'string(s)'),並且如果你真的需要重用緩衝區嘗試保存。然而,它仍然比僅僅尋找阿德里安解決方案中的第一位數的直接解決方案慢。 – JimB

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) 
} 

這裏有一個遊樂場(相同的代碼): https://play.golang.org/p/uLyBMlra2N

+1

我總是忘記,'float64'的精度使得它能夠在int64範圍內保存__any整數_而不會發生一些截斷事件?即有'int64(float64(n))!= n'的可能性,其中'n'原本是'int64'? – RayfenWindspear

+1

不,是Go 64位的整數? (我之前沒有用過Go)。 int64的範圍:2^64。完美的float64範圍:2^53,因爲你可以從尾數得到52個完美的比特,而從指數得到52個完美的比特。 – boxtrain

+1

int類型基於系統架構,但仍然是自己的類型。在x64上它將是'int64',但並不意味着類型'int'和'int64'是相同的,因此需要強制轉換。 – RayfenWindspear

相關問題