Rubyize This: Live in Vancouver. Refactoring #2
published 2008-01-27
Here's the second refactoring from the Rubyize This workshop. See the first refactoring for an explanation of what's going on and why this code is so darn ugly! Don't forget to check out the third and final refactoring
This script loads the file full of random numbers from the first refactoring and makes a beautiful ascii-art histogram from it.
#!/usr/bin/env ruby require 'pp' BIG_NUMBER = 32768 # Get data from a file, turn it in to a float, and find the max data = File.readlines('random.txt') max = -BIG_NUMBER for n in (0 ... data.length) data[n] = data[n].chomp.to_f if data[n] > max max = data[n].to_i + 1 # max is ceil(max(data[n])) end end # Create the empty histogram histogram = [] for n in (0 .. max) histogram.push(0) end # Fill the histogram for n in (0 ... data.length) histogram[data[n].to_i] += 1 end # Print the histogram pp histogram puts for n in (0 .. max) puts "*" * histogram[n] end
Here's a very concise one-liner from the crowd:
0.upto((data=File.readlines('random.txt').collect {|e| e.chomp!.to_f}).max.to_i) {|i| puts i.to_s + " " + data.select{|a| a==i}.size.to_s}
Here's Owen's refactoring:
require 'pp' histogram = [] File.readlines('random.txt').each do |value| i = value.chomp.to_i histogram[i] ||= 0 histogram[i] += 1 end # Print the histogram pp histogram puts histogram.each { | v | puts "*" * v }
Here's Sam Livingstone Gray's refactoring
#!/usr/bin/env ruby require 'pp' # Get data from a file, turn it in to a float, and find the max module Enumerable def value_counts h = Hash.new(0) each { |e| h[e] += 1 } h end end lines = File.readlines('random.txt') histogram = lines.map { |line| line.chomp.to_i }.value_counts # Print the histogram pp histogram puts histogram.keys.sort.each { |n| puts '*' * histogram[n] }
I really like this one. Sam created a simple extension to Enumerable that I can see using over and over again.
Here's what I came up with, with some debugging help from the group
#!/usr/bin/env ruby require 'pp' data = File.readlines('random.txt').collect {|datum| datum.chomp.to_f} max = data.max histogram = data.inject([0] * (max + 1)) do |histogram, datum| histogram[datum.to_i] += 1 histogram end pp histogram histogram.each do |bucket| puts "*" * bucket end