Soliciting some help with inject method

Rubysters,

I think I am not wrong if I can solicit some knowledge. :slight_smile:

Can any one help modify this code?

I have:
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

I want to create a hash using inject method:

hash = {'a' => [1, 2], 'b' => [2, 4], 'c' => [4], 'd' => [5]}

The following code gives: {"a"=>[2], "b"=>[4], "c"=>[4], "d"=>[5]}

hash = array.inject({}) do |result, array|
new_hash = {}
new_hash[array.first] = [array.last]
result.merge!(new_hash) # I have tried result.update(new_hash) but it fails
too
result
end

Here is a console friendly version of the same:
hash = array.inject({}){|result, array| new_hash = {};
new_hash[array.first] = [array.last]; result.merge!(new_hash); result;}

Thanks in advance,

路路路

---
Edmond
Software Developer | Baobab Health Trust (http://www.baobabhealth.org/\) |
Malawi

Cell: +265 999 465 137 | +265 881 234 717

*I wish you a Merry Christmas and a Prosperous New Year 2011!!**
*

array.inject({}) do |result, (key, value)|
  (result[key] ||= ) << value
  result
end

-Jeremy

路路路

On 2/2/2011 8:56 AM, Edmond Kachale wrote:

Rubysters,

I think I am not wrong if I can solicit some knowledge. :slight_smile:

Can any one help modify this code?

I have:
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

I want to create a hash using inject method:

hash = {'a' => [1, 2], 'b' => [2, 4], 'c' => [4], 'd' => [5]}

Here's one simple way to do it:

hash = array.inject({}) do |result, array|
  key,val = array
  if result[key].nil?
    result[key] = [val]
  else
    result[key].push val
  end
  result
end

路路路

On Wed, Feb 2, 2011 at 9:56 AM, Edmond Kachale < edmond.kachale@baobabhealth.org> wrote:

Rubysters,

I think I am not wrong if I can solicit some knowledge. :slight_smile:

Can any one help modify this code?

I have:
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

I want to create a hash using inject method:
>> hash = {'a' => [1, 2], 'b' => [2, 4], 'c' => [4], 'd' => [5]}

The following code gives: {"a"=>[2], "b"=>[4], "c"=>[4], "d"=>[5]}

hash = array.inject({}) do |result, array|
new_hash = {}
new_hash[array.first] = [array.last]
result.merge!(new_hash) # I have tried result.update(new_hash) but it
fails
too
result
end

Here is a console friendly version of the same:
hash = array.inject({}){|result, array| new_hash = {};
new_hash[array.first] = [array.last]; result.merge!(new_hash); result;}

Thanks in advance,

---
Edmond
Software Developer | Baobab Health Trust (http://www.baobabhealth.org/\) |
Malawi

Cell: +265 999 465 137 | +265 881 234 717

*I wish you a Merry Christmas and a Prosperous New Year 2011!!**
*

You can do this without an inject, with a simple iteration and a bit of ||=

a = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

=> [["a", 1], ["b", 2], ["a", 2], ["c", 4], ["d", 5], ["b", 4]]

h = {}

=> {}

a.each { |k, v| h[k] ||= ; h[k] << v }

=> [["a", 1], ["b", 2], ["a", 2], ["c", 4], ["d", 5], ["b", 4]]

h

=> {"a"=>[1, 2], "b"=>[2, 4], "c"=>[4], "d"=>[5]}

路路路

On Wed, Feb 2, 2011 at 2:56 PM, Edmond Kachale < edmond.kachale@baobabhealth.org> wrote:

Rubysters,

I think I am not wrong if I can solicit some knowledge. :slight_smile:

Can any one help modify this code?

I have:
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

I want to create a hash using inject method:
>> hash = {'a' => [1, 2], 'b' => [2, 4], 'c' => [4], 'd' => [5]}

The following code gives: {"a"=>[2], "b"=>[4], "c"=>[4], "d"=>[5]}

hash = array.inject({}) do |result, array|
new_hash = {}
new_hash[array.first] = [array.last]
result.merge!(new_hash) # I have tried result.update(new_hash) but it
fails
too
result
end

Here is a console friendly version of the same:
hash = array.inject({}){|result, array| new_hash = {};
new_hash[array.first] = [array.last]; result.merge!(new_hash); result;}

Thanks in advance,

---
Edmond
Software Developer | Baobab Health Trust (http://www.baobabhealth.org/\) |
Malawi

Cell: +265 999 465 137 | +265 881 234 717

*I wish you a Merry Christmas and a Prosperous New Year 2011!!**
*

Yet another way without inject:

irb(main):001:0> array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d',
5], ['b',4]]
=> [["a", 1], ["b", 2], ["a", 2], ["c", 4], ["d", 5], ["b", 4]]
irb(main):002:0> result = Hash.new {|h,k| h[k] = }
=> {}
irb(main):003:0> array.each {|key,value| result[key] << value}
=> [["a", 1], ["b", 2], ["a", 2], ["c", 4], ["d", 5], ["b", 4]]
irb(main):004:0> result
=> {"a"=>[1, 2], "b"=>[2, 4], "c"=>[4], "d"=>[5]}

Jesus.

路路路

On Wed, Feb 2, 2011 at 3:56 PM, Edmond Kachale <edmond.kachale@baobabhealth.org> wrote:

Rubysters,

I think I am not wrong if I can solicit some knowledge. :slight_smile:

Can any one help modify this code?

I have:
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

I want to create a hash using inject method:

hash = {'a' => [1, 2], 'b' => [2, 4], 'c' => [4], 'd' => [5]}

The following code gives: {"a"=>[2], "b"=>[4], "c"=>[4], "d"=>[5]}

hash = array.inject({}) do |result, array|
new_hash = {}
new_hash[array.first] = [array.last]
result.merge!(new_hash) # I have tried result.update(new_hash) but it fails
too
result
end

Here is a console friendly version of the same:
hash = array.inject({}){|result, array| new_hash = {};
new_hash[array.first] = [array.last]; result.merge!(new_hash); result;}

Thanks in advance,

Thanks Adam. I just reduced your lines to make it geeky!! :slight_smile:

hash = array.inject({}) do |result, (key, value)|
  (result[key].nil?) ? (result[key] = [value]) : (result[key].push(value))
  result
end

路路路

2011/2/2 Andrew Wagner <wagner.andrew@gmail.com>

Here's one simple way to do it:

hash = array.inject({}) do |result, array|
  key,val = array
if result[key].nil?
   result[key] = [val]
else
   result[key].push val
end
result
end

---
Edmond
Software Developer | Baobab Health Trust (http://www.baobabhealth.org/\) |
Malawi

Cell: +265 999 465 137 | +265 881 234 717*
**
An old dog does not hunt because of speed, but his endurance of the heart*

Sorry, I meant Andrew.

But I also value you contribution, Adam and Jes没s. In fact, I think your
methods are faster than the inject's way.

路路路

Le 2 f茅vrier 2011 17:46:42 UTC+2, edmond.kachale < edmond.kachale@baobabhealth.org> a 茅crit :

2011/2/2 Andrew Wagner <wagner.andrew@gmail.com>

Here's one simple way to do it:

hash = array.inject({}) do |result, array|
  key,val = array
if result[key].nil?
   result[key] = [val]
else
   result[key].push val
end
result
end

Thanks Adam. I just reduced your lines to make it geeky!! :slight_smile:

hash = array.inject({}) do |result, (key, value)|
  (result[key].nil?) ? (result[key] = [value]) : (result[key].push(value))
  result
end

---
Edmond
Software Developer | Baobab Health Trust (http://www.baobabhealth.org/\) |
Malawi

Cell: +265 999 465 137 | +265 881 234 717*
**
An old dog does not hunt because of speed, but his endurance of the heart.*
*
*

But I also value you contribution, Adam and Jes没s. In fact, I think your
methods are faster than the inject's way.

You'd be surprised :-). If I didn't do anything wrong (I usually make
mistakes when benchmarking), my method is the slowest:

require 'benchmark'

TIMES = 100_000
array = [['a', 1], ['b', 2], ['a',2], ['c',4], ['d', 5], ['b',4]]

Benchmark.bm do |x|
  x.report "inject Jeremy" do
    TIMES.times do
      array.inject({}) do |result, (key, value)|
        (result[key] ||= ) << value
        result
      end
    end
  end

  x.report "Adam" do
    TIMES.times do
      result = {}
      array.each { |k, v| result[k] ||= ; result[k] << v }
    end
  end

  x.report "inject Andrew" do
    TIMES.times do
      hash = array.inject({}) do |result, values|
        key,val = values
        if result[key].nil?
          result[key] = [val]
        else
          result[key].push val
        end
        result
      end
    end
  end

  x.report "Jesus" do
    TIMES.times do
      result = Hash.new {|h,k| h[k] = }
      array.each {|key,value| result[key] << value}
    end
  end
end

$ ruby bm_inject.rb
      user system total real
inject Jeremy 1.440000 0.300000 1.740000 ( 1.770496)
Adam 1.100000 0.190000 1.290000 ( 1.290073)
inject Andrew 1.810000 0.210000 2.020000 ( 2.064162)
Jesus 1.800000 0.320000 2.120000 ( 2.118433)

I guess it's because you need to call the default proc many times, as
opposed to the other methods, which don't have any proc to call or
block to yield to.

Jesus.

On Wed, Feb 2, 2011 at 11:52 PM, Edmond Kachale > But I also value you
contribution,

... are faster than the inject's way.

inject is a lot faster in 1.9
its added adv is that you lessen the use of temp vars and everything
is encap in the method..

eg, using jeremy bopps technique, one would do

a.inject(Hash.new{|hash,key| hash[key]=}) do |hash,(key,value)|
  hash[key] << value
  hash
end

or add a touch of tap,

a.inject(Hash.new{|h,k| h[k]=}) do |h,(k,value)|
  h.tap{|h| h[k] << value}
end

best regards -botp