5
\$\begingroup\$

I'm trying to optimize this bit of code and I thought I'd throw it out here to see if anyone has any ideas. I've been testing the performance using Benchmark.measure {...} and wrapping the entire function.

Yes, the item has a date that is a Ruby Date

 puts Benchmark.measure {
 grouped_items
 }
 def grouped_items
 unless @grouped
 @grouped = {}
 @items.each do |item|
 key = item.date
 if @grouped.has_key?(key)
 @grouped[key] << item
 else
 @grouped[key] = [item]
 end
 end
 end
 @grouped
 end

Thanks for any insight you care to share.

Edit #1: My first optimization. I was aiming for a slightly more succinct function and gained a .2 seconds reduction in time to process 100_000 items.

 def grouped_items
 unless @grouped
 @grouped = Hash.new { |h, k| h[k] = [] }
 @items.map {|item| @grouped[item.date] << item }
 end
 @grouped
 end

Edit #2: My second iteration with more or less the same performance profile but with much less code.

def grouped_items
 @grouped ||= @items.group_by { |item| item.date }
end

Edit #3: An alternative way to do the same thing above.

def grouped_items
 @grouped ||= @items.group_by &:date
end
asked Jul 7, 2012 at 1:25
\$\endgroup\$
3
  • \$\begingroup\$ Nope. I'll check that out. \$\endgroup\$ Commented Jul 7, 2012 at 1:21
  • \$\begingroup\$ In future can you flag for a mod to migrate, please don't cross-post. Thanks. \$\endgroup\$ Commented Jul 8, 2012 at 0:58
  • \$\begingroup\$ Did you try profiling the code? \$\endgroup\$ Commented Jul 12, 2012 at 2:41

2 Answers 2

8
\$\begingroup\$

Are you aware of Enumerable#group_by?

def grouped_items
 @items.group_by{|item| item.date}
end
answered Jul 7, 2012 at 1:37
\$\endgroup\$
4
  • \$\begingroup\$ It more or less performs the same as the first edit (see above) but with much less code. \$\endgroup\$ Commented Jul 7, 2012 at 1:44
  • 1
    \$\begingroup\$ I just came back across this and wanted to comment again how awesome this solution is. :) \$\endgroup\$ Commented Jul 29, 2012 at 17:44
  • \$\begingroup\$ Just to add, you could even use symbol-to-proc here since you are grouping by an immediate method call: @items.group_by &:date. \$\endgroup\$ Commented Dec 16, 2014 at 9:39
  • \$\begingroup\$ Indeed, as the OP discovered and showed in his Edit #3. \$\endgroup\$ Commented Dec 16, 2014 at 14:24
4
\$\begingroup\$

What about this?

@items.group_by { |item| item.effective_date }

Benchmarks for the curious:

Ryan v1 : 1.080000 0.000000 1.080000 ( 1.077599)
Ryan v2 : 0.620000 0.000000 0.620000 ( 0.622756)
group_by: 0.580000 0.000000 0.580000 ( 0.576531)
answered Jul 7, 2012 at 1:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.