fail_lord fail_lord - 4 months ago 9
Ruby Question

Efficiency of Ruby code: hash of month + frequency into formatted sorted array

I've hacked up some code that fulfills its purpose but it feels very clunky/inefficient. From a table of many entries, each has a month + year string associated with it: "September 2016" etc. From these I create a chronologically ordered array of months and their frequencies to be used in a dropdown selection form: ['Novemeber 2016 (5)', 'September 2016 (5)'].

@months = []

banana = Post.pluck(:month)
#array of all months posted in, eg ['September 2016', 'July 2017', etc

strawberry = banana.each_with_object(Hash.new(0)){|key,hash| hash[key] += 1}
#hash of unique month + frequency

strawberry.each { |k, v| strawberry[k] = "(#{v.to_s})" }
#value into string with brackets

pineapple = (strawberry.sort_by { |k,_| Date.strptime(k,"%b %Y") }).reverse
#sorts into array of months ordered by most recent

pineapple.each { |month, frequency| @months.push("#{month}" + " " + "#{frequency}") }
#array of formatted months + frequency, eg ['July 2017 (5)', 'September 2016 (5)']


I was hoping some of the Ruby gurus here could advise me in some ways to improve this code. Any ideas or suggestions would be greatly appreciated!

Thanks!

Answer
['September 2016', 'July 2017', 'September 2016', 'July 2017']
  .group_by { |e| e } # .group_by(&:itself) since Ruby2.3
  .sort_by { |k, _| Date.parse(k) }
  .reverse
  .map { |k, v| "#{k} (#{v.count})" }

#⇒ [
#  [0] "July 2017 (2)",
#  [1] "September 2016 (2)"
# ]
Comments