3
\$\begingroup\$

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
]
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

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:

  1. Point on naming: use a verb, or else a noun describing what the function returns: sort_alphabetically or alphabetically_sorted. I know technically alphabetically_sorted isn't a noun, but I see it as an abbreviation for alphabetically_sorted_list, which is too verbose.

  2. If speed matters, you should compute the hash outside the function, so it's only done once.

\$\endgroup\$
1
  • \$\begingroup\$ Nice, thank you. I will study this further. Also, I think I accidentally "down voted" you answer :/ \$\endgroup\$
    – Nathan
    Sep 18, 2017 at 9:24
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.