I don't really understand inject

I think these methods should both do the same thing. The second works,
however in the first I get errors that string is not matched, where
hash is an instance of String not hash

def sequences
    self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
      id, sequence = line.split(/\s+/,2)
      # hash.class == String
      hash[id] = sequence
    end
end

  def sequences
    hash = Hash.new
    self.alignment.split(/\n/).each do |line|
      id, sequence = line.split(/\s+/,2)
      # hash.class == Hash
      hash[id] = sequence
    end
    hash
  end

I think these methods should both do the same thing. The second works,
however in the first I get errors that string is not matched, where
hash is an instance of String not hash

def sequences
   self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
     id, sequence = line.split(/\s+/,2)
     # hash.class == String
     hash[id] = sequence

     hash # value of block will be the last expression

   end
end

def sequences
   hash = Hash.new
   self.alignment.split(/\n/).each do |line|
     id, sequence = line.split(/\s+/,2)
     # hash.class == Hash
     hash[id] = sequence
   end
   hash
end

The value of the block becomes the first block parameter in the next iteration.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

···

On Jun 19, 2008, at 9:13 AM, Mike Barton wrote:

How inject works is that it passes the block two values:
an accumulator and one of the elements in the enumerable
(one at a time). In each iteration, the accumulator will be the
return value of the block in the previous iteration.

So in your example, if you want the accumulator to be a hash,
your block should return a hash. Try this (untested):

def sequences
    self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
      id, sequence = line.split(/\s+/,2)
      # hash.class == String
      hash[id] = sequence
      hash # <<< the change
    end
end

Hope this helps,

Jesus.

···

On Thu, Jun 19, 2008 at 3:13 PM, Mike Barton <barton.michael@gmail.com> wrote:

I think these methods should both do the same thing. The second works,
however in the first I get errors that string is not matched, where
hash is an instance of String not hash

def sequences
   self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
     id, sequence = line.split(/\s+/,2)
     # hash.class == String
     hash[id] = sequence
   end
end

I see, I see, I see.
That solved the problem. Thanks for that help injection!
Ha Ha Ha!

···

On Jun 19, 2:36 pm, Jesús Gabriel y Galán <jgabrielyga...@gmail.com> wrote:

On Thu, Jun 19, 2008 at 3:13 PM, Mike Barton <barton.mich...@gmail.com> wrote:
> I think these methods should both do the same thing. The second works,
> however in the first I get errors that string is not matched, where
> hash is an instance of String not hash

> def sequences
> self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
> id, sequence = line.split(/\s+/,2)
> # hash.class == String
> hash[id] = sequence
> end
> end

How inject works is that it passes the block two values:
an accumulator and one of the elements in the enumerable
(one at a time). In each iteration, the accumulator will be the
return value of the block in the previous iteration.

So in your example, if you want the accumulator to be a hash,
your block should return a hash. Try this (untested):

def sequences
self.alignment.split(/\n/).inject(Hash.new) do |hash, line|
id, sequence = line.split(/\s+/,2)
# hash.class == String
hash[id] = sequence
hash # <<< the change
end
end

Hope this helps,

Jesus.

Nice one, fortunately you did not ask for help on reduce (which is an
alias of inject) ;).
Robert

···

On Thu, Jun 19, 2008 at 4:08 PM, Mike Barton <barton.michael@gmail.com> wrote:

I see, I see, I see.
That solved the problem. Thanks for that help injection!
Ha Ha Ha!