0

So, I am trying to define a method #my_array_sorting_method that will take an array(source) as input and take the array's elements (both integers and strings) and sort them alphabetically and display this, all without altering the original array structure. This is what I have so far:

def my_array_sorting_method(source)
   source.sort_by { |a,b| a <=> b }
end

I assumed by using a nondestructive method that it would do what I wanted, but I am still getting an error message when I run the code:

'my_array_sorting_method! converts sorts all elements alphabetically without altering changing data'

If anyone can help me out here, it would be hugely appreciated. I am a Ruby newbie and I'm really stuck here.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • Welcome Brendon! Are you sure you're calling it with `sort_by` and not `sort_by!` ? Exclamation marks or "bangs" signal that the method modifies the object it is called on. #RubyConvention – Breedly Apr 10 '15 at 16:41
  • `sort_by` will be slower than using `sort` if all you are doing is a simple comparison of `a <=> b`. See "[Sorting an array in descending order in Ruby](http://stackoverflow.com/questions/2642182/sorting-an-array-in-descending-order-in-ruby/2651028#2651028)" for more information. – the Tin Man Apr 10 '15 at 17:52
  • @theTinMan I wouldn't suggest he worry about performance yet. It's more important for him to know that he's passing the wrong block into `sort_by`. – Kache Apr 10 '15 at 21:29
  • Being aware that one way is faster than another, especially when it's the difference between `sort` and `sort_by` is very important. There can be remarkable differences in performance between the two as a result of a very simple change in coding. – the Tin Man Apr 10 '15 at 21:49

1 Answers1

0

Sorting

If you look up ruby documentation, you'll find a few different sorting methods at your disposal for Enumerable objects (like Array), primarily sort and sort_by and their variations.

Both sort and sort_by return a new sorted Array without modifying the original.

Enumerable#sort

Pass in a block telling it how to compare two objects.

unsorted = 5.times.map { rand(100) }
new_sorted_array = unsorted.sort { |x, y| x <=> y }
new_sorted_array = unsorted.sort # this is equivalent because we're only using the default comparator, <=>
puts "still unsorted: #{unsorted.inspect}"
puts "sorted: #{new_sorted_array.inspect}"

Enumerable#sort_by

Pass in a block that retrieves the key by which the objects should be sorted (using the default comparator, <=>, i think)

unsorted_wrapped_numbers = 5.times.map { [rand(100)] }
new_sorted_array = unsorted_wrapped_numbers.sort_by { |wrapped_number| wrapped_number.first }
puts "still unsorted: #{unsorted_arrays_of_single_numbers.inspect}"
puts "sorted: #{new_sorted_array.inspect}"

Note that this information is all available online, and I've linked each section above to its relevant ruby documentation. I often refer to them, myself.

Comparing "alphabetically"

By default, integers are comparable with integers and strings with strings, using the default comparator, <=>:

94 <=> 2 # returns 1, meaning "greater than"
3 <=> 3 # returns 0, meaning "equal"
"goodbye" <=> "hello" # returns -1, meaning "less than", since "g" comes before "h", alphabetically

You'll need to define how an integer is going to be compared to a string, though:

5 <=> "word" # returns nil

Consider converting the number into a string, for example:

5.to_s <=> "word"
Community
  • 1
  • 1
Kache
  • 15,647
  • 12
  • 51
  • 79
  • Thank you so much, that really cleared a lot of stuff up for me. It was just a simple .to_s method I didn't use. Here's the solution I came up with: def my_array_sorting_method(source) source.sort_by {|a,b| a.to_s} end – Brendon Laffey Apr 11 '15 at 21:31
  • Remove the variable b. It's extraneous and doesn't do anything. Also, if you find my post helpful, would you mind accepting it as the answer? – Kache Apr 12 '15 at 01:20