On 24.08.2007 23:40, Stefan Rusterholz wrote:
> Greg Kujawa wrote:
>> On Aug 24, 9:52 am, "Robert Klemme" <shortcut... / googlemail.com>
>> wrote:
>>>>> [["Value A", "Value B", 3], ["Value A", "Value C", 2],["Value A",
>>>>> that will suit the task?
>>>> "Value B", 1]]
>>>> hash[ elem[0,2] ] += elem[2]; hash }.collect { |k, v|  k + [v] }
>>> => {["Value A", "Value C"]=>2, ["Value A", "Value B"]=>4}
>>> irb(main):007:0> arr.inject(Hash.new(0)) {|ha,(a,b,c)|
>>> ha[[a,b]]+=c;ha}.map {|x| x.flatten}
>>> => [["Value A", "Value C", 2], ["Value A", "Value B", 4]]
>>>
>>> At least 1 #inject. :-)
>>>
>>> Kind regards
>>>
>>> robert- Hide quoted text -
>>>
>>> - Show quoted text -
>> Thanks guys. All of the insight helps me out tremendously. There are a
>> lot of abilities that I never tapped into along these lines. Great
>> stuff and hopefully more tools in my belt. Appreciate the tips!
> 
> What makes me slightly sad is that all those examples try to squeeze as 
> much as possible into a single statement.

That was not my primary concern.  I tried to avoid pasting lengthy IRB 
screen copies as they tend to look horrible.  The code could have been 
on more lines as well.

> Frankly, in my opinion the 
> resulting code is horrible to read again a few months later.

I'd say: it depends.  People seem to be quite different with regard to 
their "readability ranking".  I know people who prefer shorter code. 
Since this is not production code and especially without explicit 
comments (there's always the mail / news thread) it's not intended to be 
easily readable after a longer period of time.

> I'll try to go a different way, a bit more to type but hopefully easier 
> to read. Maybe somebody has an even more readable idea.
> 
> array  = [["Value A", "Value B", 3], ["Value A", "Value C", 2],["Value 
> A", "Value B", 1]]
> groups = array.group_by { |element| element.first(2) }
> result = groups.map { |key, values|
>   values.map! { |a,b,c| c } # if I knew what each value represents I'd 
> chose better names
>   key+[values.sum]
> }

What I dislike about this solution is that it traverses the collection 
twice although it is more modular.  If I want very readable code I'd do 
something like this:

array = ...
groups = Hash.new 0
array.each do |(a,b,c)|
p a
   groups[[a,b]] +=  c
end
result = groups.to_a

> # required code (group_by is in 1.9, though probably a different 
> implementation, sum is in activesupport afaik)
> module Enumerable
>   def group_by(result=nil, add=nil)
>     result ||= Hash.new { |h,k| h[k]=[] }
>     add    ||= :<<
>     each { |args| result[yield(args)].__send__(add, args) }
>     result
>   end
> end

Personally I would not make the Hash and add an argument here because 
there are too many requirements.  (I.e. result needs to guarantee that 
result[] will return something that can receive the method you use).

> module Enumerable
>   def sum
>     inject(0) { |a,b| a+b }
>   end
> end

Note that this implementation of sum only works for numeric types.  It 
does not work for example for string concatenation.

Kind regards

	robert