Given the following array:
y = %w[A1 A2 B5 B12 A6 A8 B10 B3 B4 B8]
=> [\"A1\", \"A2\", \"B5\", \"B12\", \"A6\", \"A8\", \"B10\", \"B3\", \"B4\", \"B8\"]
You are sorting strings. Strings are sorted like strings, not like numbers. If you want to sort like numbers, then you should sort numbers, not strings. The string 'B10'
is lexicographically smaller than the string 'B3'
, that's not something unique to Ruby, that's not even something unique to programming, that's how lexicographically sorting a piece of text works pretty much everywhere, in programming, databases, lexicons, dictionaries, phonebooks, etc.
You should split your strings into their numerical and non-numerical components, and convert the numerical components to numbers. Array sorting is lexicographic, so this will end up sorting exactly right:
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"]