2016-08-18 39 views
0

鑑於以下陣列工作紅寶石字母排序並不如預期

=> ["A1", "A2", "A6", "A8", "B3", "B4", "B5", "B8", "B10", "B12"] 

使用以下(香草)排序,我得到:

irb(main):2557:0> y.sort{|a,b| puts "%s <=> %s = %s\n" % [a, b, a <=> b]; a <=> b} 
A1 <=> A8 = -1 
A8 <=> B8 = -1 
A2 <=> A8 = -1 
B5 <=> A8 = 1 
B4 <=> A8 = 1 
B3 <=> A8 = 1 
B10 <=> A8 = 1 
B12 <=> A8 = 1 
A6 <=> A8 = -1 
A1 <=> A2 = -1 
A2 <=> A6 = -1 
B12 <=> B3 = -1 
B3 <=> B8 = -1 
B5 <=> B3 = 1 
B4 <=> B3 = 1 
B10 <=> B3 = -1 # this appears to be wrong, looks like 1 is being compared, not 10. 
B12 <=> B10 = 1 
B5 <=> B4 = 1 
B4 <=> B8 = -1 
B5 <=> B8 = -1 
=> ["A1", "A2", "A6", "A8", "B10", "B12", "B3", "B4", "B5", "B8"] 

......這顯然不是我所希望的。我知道我可以嘗試首先在alpha上分割,然後對數值進行排序,但似乎我不應該那樣做。

可能重要的提醒:我們使用Ruby卡住1.8.7現在:(但即使紅寶石2.0.0做同樣的事情缺少什麼我在這裏

建議

+3

您的第一個預感是正確的;因爲這些是字符串,它們將按照字典順序排列。如果你想把這個數字作爲排序的一個元素,你需要將這個數字與數字分開,並在分類時使用它自己的意願。 – Makoto

+2

我很好奇你爲什麼認爲*字符串*「B12」會在*字符串*「B2」之前排序。這不是Ruby如何對字符串進行排序的方式,這就是* everything *字符串的排序方式。 – meagar

+0

你想'y.sort_by {| s | [s [0],s [1..-1] .to_i]}#=> [「A1」,「A2」,「A6」,「A8」,「B3」,「B4」,「B5」 「B8」,「B10」,「B12」]。關於Ruby如何對數組進行排序,請參見[Array#<=>](http://ruby-doc.org/core-2.3.0/Array.html#method-i-3C-3D-3E)。 –

回答

1

您正在排序字符串。字符串按字符串排序,不像數字。如果你想排序像數字,那麼你應該排序數字,而不是字符串。字符串'B10'在字典順序上比字符串'B3'小,這不是Ruby獨有的,甚至不是編程所特有的東西,這就是在編程,數據庫,詞典,字典,電話簿等中按字母順序排列一段文本的方法。等等。

您應該將您的字符串拆分爲它們的數字和非數字分量,並將數字分量轉換爲數字。陣列排序是詞典編排,所以這將最終排序完全正確:

y.sort_by {|s| # use `sort_by` for a keyed sort, not `sort` 
    s. 
    split(/(\d+)/). # split numeric parts from non-numeric 
    map {|s| # the below parses numeric parts as decimals, ignores the rest 
     begin Integer(s, 10); rescue ArgumentError; s end }} 
#=> ["A1", "A2", "A6", "A8", "B3", "B4", "B5", "B8", "B10", "B12"] 
-1

?A?自然或詞典排序,而不是一個標準的基於字符值的排序,就像這些寶石將是一個起點:https://github.com/dogweather/naturally,https://github.com/johnnyshields/naturalsort

人類視爲「A」字符串爲「A」後跟數字2,然後使用字符串排序對字符串部分和數字排序進行排序RT。標準sort()使用字符值排序將字符串視爲字符序列,而不管字符是什麼。因此,對於sort()「A10」和「A2」看起來像['A','1','0']和['A','2'],因爲'1'在'2'之前排序,並且以下字符可以因此不會改變該訂單「A10」因此在「A2」之前排序。對於人類來說,相同的字符串看起來像[「A」,10]和[「A」,2],10之後有10種,所以我們得到相反的結果。可以通過操縱字符串使基於字符值的sort()產生預期的結果,方法是將左側的數字部分固定寬度和零填充以避免嵌入空格,從而使「A2」變成「A02」使用標準sort()在「A10」之前排序。

+0

這實際上解決了這個問題,但它並不能解釋爲什麼這種排序不能用於開箱即用。非常有趣,但。 – Jim

+1

數字值的排序方式與其字符串表示的字符排序不同。字符值排序不適用於例如。 「A10」和「A2」,因爲'1'的字符值小於'2',這使得「A10」在「A2」之前排序。 OTOH將自然類型解釋爲「A2」等同於「A02」或[「A」,2](我們將其視爲「A」,然後是數字2)。 –

+1

注意:以上就是爲什麼在數據文件中經常在固定寬度的固定小數位零填充字段中看到右對齊的數字,以便字符排序與數字排序的結果匹配。 –