I don't really understand inject

M

Mike Barton

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
 
R

Rob Biedenharn

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
(e-mail address removed)
 
J

Jesús Gabriel y Galán

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.
 
M

Mike Barton

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

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.
 
R

Robert Dober

I see, I see, I see.
That solved the problem. Thanks for that help injection!
Ha Ha Ha!
Nice one, fortunately you did not ask for help on reduce (which is an
alias of inject) ;).
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,665
Latest member
salkete

Latest Threads

Top