greg.kujawa
8/24/2007 2:46:00 PM
On Aug 24, 9:52 am, "Robert Klemme" <shortcut...@googlemail.com>
wrote:
> 2007/8/24, Yossef Mendelssohn <ymen...@pobox.com>:
>
>
>
>
>
> > On Aug 24, 7:50 am, gregarican <greg.kuj...@gmail.com> wrote:
> > > I have an array that I would like to combine elements. Here's a sample
> > > array:
>
> > > [["Value A", "Value B", 3], ["Value A", "Value C", 2],["Value A",
> > > Value B", 1]]
>
> > > What I would like to do is find the elements where the first two items
> > > are the same and then combine the third. The resulting array would
> > > consist of:
>
> > > [["Value A", "Value B", 4],["Value A", "Value C", 2]]
>
> > > This is something that is out in left field in terms of how I've used
> > > arrays in the past. Anyone know of a quick bit of script I can whip up
> > > that will suit the task?
>
> > irb(main):001:0> orig_array = [["Value A", "Value B", 3], ["Value A",
> > "Value C", 2],["Value A", "Value B", 1]]
> > => [["Value A", "Value B", 3], ["Value A", "Value C", 2], ["Value A",
> > "Value B", 1]]
> > irb(main):002:0> hash = Hash.new(0)
> > => {}
> > irb(main):003:0> orig_array.each { |elem| hash[ elem[0,2] ] +=
> > elem[2] }
> > => [["Value A", "Value B", 3], ["Value A", "Value C", 2], ["Value A",
> > "Value B", 1]]
> > irb(main):004:0> hash.collect { |k, v| k + [v] }
> > => [["Value A", "Value C", 2], ["Value A", "Value B", 4]]
>
> > or, more concisely
>
> > irb(main):001:0> orig_array = [["Value A", "Value B", 3], ["Value A",
> > "Value C", 2],["Value A", "Value B", 1]]
> > => [["Value A", "Value B", 3], ["Value A", "Value C", 2], ["Value A",
> > "Value B", 1]]
> > irb(main):002:0> orig_array.inject(Hash.new(0)) { |hash, elem|
> > hash[ elem[0,2] ] += elem[2]; hash }.collect { |k, v| k + [v] }
> > => [["Value A", "Value C", 2], ["Value A", "Value B", 4]]
>
> I believe there is an even simpler solution:
>
> irb(main):001:0> arr=[["Value A", "Value B", 3], ["Value A", "Value
> C", 2], ["Value A", "Value B", 1]]
> => [["Value A", "Value B", 3], ["Value A", "Value C", 2], ["Value A",
> "Value B", 1]]
>
> irb(main):003:0> arr.inject(Hash.new(0)) {|ha,(a,b,c)| ha[[a,b]]+=c;ha}
> => {["Value A", "Value C"]=>2, ["Value A", "Value B"]=>4}
>
> irb(main):004:0> arr.inject(Hash.new(0)) {|ha,(a,b,c)|
> ha[[a,b]]+=c;ha}.inject([]) {|re,v| re<<v.flatten}
> => [["Value A", "Value C", 2], ["Value A", "Value B", 4]]
>
> Of course, the most elegant solution uses #inject - in this case two
> injects. :-)
>
> Although, this one might be even better:
>
> 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!