简体   繁体   中英

call function in the map block of hash

I am using Ruby version 1.8 because of legacy reason.

I have multiple hashes. I have a code logic that applies to the map block on all my hashes.

hash1.map{|a| a['amount'].to_i * a['value'].to_i / 100}

I don't want to repeat that code logic every where like:

hash2.map{|a| a['amount'].to_i * a['value'].to_i / 100}
hash3.map{|a| a['amount'].to_i * a['value'].to_i / 100}

How can I pass a function call to the block so that the code logic would only be in a function which is easier for me to maintain?

I think the simplest thing would be to make a method that accepts that hash as an argument.

def map_totals(hash)
  hash.map do |a|
    a['amount'].to_i * a['value'].to_i / 100
  end
end

totals1 = map_totals(hash1)
totals2 = map_totals(hash2)
totals3 = map_totals(hash3)

Or...

def calc_total(line_item)
  line_item['amount'].to_i * line_item['value'].to_i / 100
end

totals1 = hash1.map { |li| calc_total(li) }
totals2 = hash2.map { |li| calc_total(li) }
totals3 = hash3.map { |li| calc_total(li) }

You could use a Proc in that scenario:

calc = proc { |a| a['amount'].to_i * a['value'].to_i / 100 }

hash1.map(&calc)
hash2.map(&calc)
hash3.map(&calc)

I'm not sure if the proc { ... } syntax is available in Ruby 1.8, if not use Proc.new { ... } instead.


If you've already have the calculation defined in a method you could also pass that method:

# for example:
def calc(a)
  a['amount'].to_i * a['value'].to_i / 100
end

# or
module Helpers
  def self.calc(a)
    a['amount'].to_i * a['value'].to_i / 100
  end
end

def do_stuff
  hash1.map(&method(:calc)) # use the method #calc of self
  hash2.map(&self.method(:calc)) # same as the line above
  hash3.map(&Helpers.method(:calc)) # use the method #calc of the Helpers module
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM