Using injection in Ruby? [duplicate]

2019-08-03 13:34发布

问题:

This question already has an answer here:

  • How to implement injection in Ruby? 1 answer

I have a class called Hsh which basically simulates a hash. It has an array of Couple objects (which hold fields named one and two, one is an int another is a string name of that int).

I am supposed to be able to accept the following call:

h = x.inject({}) {|a, b| a[b.one] = b.two; a}

Where x is the Hsh object.

I am not sure how to implement the inject method within Hsh? Like, what would I write in:

def inject ????
??
??
end

All it's supposed to do is create a hash map.

回答1:

require 'ostruct'

class Hsh
  include Enumerable

  def initialize
    @arr = (0..9).map{ |i| OpenStruct.new(:one => i, :two => "#{i}")}
  end

  def each(&block)
    @arr.each(&block)
  end
end

p Hsh.new.inject({}) {|a, b| a[b.one] = b.two; a} 
#=> {5=>"5", 0=>"0", 6=>"6", 1=>"1", 7=>"7", 2=>"2", 8=>"8", 3=>"3", 9=>"9", 4=>"4"}

In this particular case Hsh is actually an array, so unless you use it for something else such a complex code doesn't make sense, it can be done much easier:

p (0..9).map{ |i| OpenStruct.new(:one => i, :two => "#{i}")} \
  .inject({}) {|a, b| a[b.one] = b.two; a} 
#=> {5=>"5", 0=>"0", 6=>"6", 1=>"1", 7=>"7", 2=>"2", 8=>"8", 3=>"3", 9=>"9", 4=>"4"}


回答2:

you shouldn't really need to implement it, just implement Hsh#eachand include Enumerable, you'll get inject for free.

For your specific example something like this should work:

def inject accumulator
   #I assume Hsh has some way to iterate over the elements
   each do |elem|
    accumulator = yield accumulator, elem
   end
   accumulator
end

But the real implementation of inject is a bit different (e.g. works without providing an accumulator, takes a symbol instead of a block etc)



回答3:

I have used OpenStruct instead of classes. See if this works for you

require 'ostruct'

class Hsh
  attr_accessor :arr

  def initialize
    obj = OpenStruct.new
    obj.one = 1
    obj.two = "two"
    @arr = [obj] 
  end

  def inject(hash)
    @arr.each do |arr|
      yield hash, arr
    end
    hash  
  end  
end

x = Hsh.new
p x.inject({}) {|a, b| a[b.one] = b.two} #prints {1 => "two"}