This exercise involves taking an array of numbers and sorting them alphabetically. For example, [1,2,3,4] would return as [4,1,3,2]
I mapped the array first, returning an array of words, then sorted those words using Ruby's built-in sort function. Then, I mapped that array to return an array of integers.
It works, obviously. I want your suggestions and thoughts, different ideas and better ways I could do this in the future.
I know I could one-line the map functions, but thought this is better for readability. Example: alphabeticize = numbers.map {|num| alphas.fetch(:"#{num.to_s}")}.sort
def alphabetic_number_sort(numbers)
alphas = {"0": "zero", "1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six", "7": "seven", "8": "eight", "9": "nine", "10": "ten", "11": "eleven", "12": "twelve", "13": "thirteen", "14": "fourteen", "15": "fifteen", "16": "sixteen", "17": "seventeen", "18": "eighteen", "19": "nineteen"}
alphabeticize = numbers.map do |num|
alphas.fetch(:"#{num.to_s}")
end.sort
sorted_alphabetically = alphabeticize.map do |word|
alphas.key(word).to_s.to_i
end
return sorted_alphabetically
end
p alphabetic_number_sort((0..19).to_a) == [
8, 18, 11, 15, 5, 4, 14, 9, 19, 1, 7, 17,
6, 16, 10, 13, 3, 12, 2, 0
]
2 Answers 2
sort_by
cleans this up quite a bit, and avoids the unnecessary conversions to and from strings:
def sort_alphabetically(numbers)
alphas = %w(zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen)
.map.with_index {|x,i| [i, x]}.to_h
numbers.sort_by {|x| alphas[x]}
end
Notes:
Point on naming: use a verb, or else a noun describing what the function returns:
sort_alphabetically
oralphabetically_sorted
. I know technicallyalphabetically_sorted
isn't a noun, but I see it as an abbreviation foralphabetically_sorted_list
, which is too verbose.If speed matters, you should compute the hash outside the function, so it's only done once.
-
\$\begingroup\$ Nice, thank you. I will study this further. Also, I think I accidentally "down voted" you answer :/ \$\endgroup\$Nathan– Nathan2017年09月18日 09:24:55 +00:00Commented Sep 18, 2017 at 9:24
When defining the alphas
hash, I would consider strings to be more appropriate as keys than symbols. That would help eliminate the awkward colon during lookup in alphas.fetch(:"#{num.to_s}")
.
However, I question the need for a hash at all. Why not write it as an array?
ENGLISH_NUMS = %w(
zero one two three four five six seven eight nine
ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen
)
Then, it's a simple matter of using Enumerable#sort_by
.
def alphabetic_number_sort(numbers)
numbers.sort_by { |n| ENGLISH_NUMS[n] }
end
Note that it is common practice to omit the explicit return
in Ruby.