4

Here is my ruby code:

books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]

books.sort! {

  |firstBook, secondBook|
  boolean_value = firstBook <=> secondBook
  print "first book is =  '#{firstBook}'"
  print " , second book is = '#{secondBook}'"
  puts  " and there compare result is #{boolean_value}"

}

Questions:

  1. This code runs single iteration and then it gives error in 'sort!': comparison of String with String failed (ArgumentError)
  2. When firstbook = "Charlie and the Chocolate Factory" then secondBook should be "War and Peace" but it code chooses "Utopia" to compare. Why?
paul
  • 4,333
  • 16
  • 71
  • 144
  • 1. Array#sort! expect the block to return a number, your last statement puts return nil instead. 2. My guess is that Array#sort! use quicksort to compare, so "Utopia" is chosen as the pivot – Vu Minh Tan Nov 18 '14 at 09:00
  • I got this error when I used 'sort' on an array that unintentionally had mixed string and integer values. The string values were strings of integers, so suffixing ".to_i" on the string array elements when they were initialized solved the problem. No other StackOverflow question seems to address this. – Leonard Dec 04 '22 at 16:20

1 Answers1

5

Make sure you return the comparison result from the block you passed to sort!.

Currently, you return nil (the return value of the last statement, the puts) and this leads to unpredictable results.

Change your code to:

books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]

books.sort! {

  |firstBook, secondBook|
  boolean_value = firstBook <=> secondBook
  print "first book is =  '#{firstBook}'"
  print " , second book is = '#{secondBook}'"
  puts  " and there compare result is #{boolean_value}"

  boolean_value  # <--- this line has been added
}

and everything will work.


Offtopic, a few nitpicks:

  • in Ruby, the convention is to separate words with underscore in variable names. For example, you should rename firstBook -> first_book
  • you should be very careful when naming variables. The variable boolean_value is a bit misleading here, because it's not true or false, its -1, 0, or 1.
Cristian Lupascu
  • 39,078
  • 16
  • 100
  • 137
  • 1
    Superb. Thanks for valuable advice.But why it chose "utopia" to compare as second book. – paul Nov 18 '14 at 09:00
  • 2
    @paul I don't know exactly, but if I were to take a wild guess, I'd say that Ruby is using QuickSort under the cover, and *Utopia* is chosen as the quicksort pivot. [Apparently the middle element is a reasonable candidate for the pivot](http://stackoverflow.com/a/164177/390819). – Cristian Lupascu Nov 18 '14 at 09:07