Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding Hashes from an array

I am trying to create an array/hash from an array of multiple hashes with same keys and an average of values. My array:

[{:amount=>897500, :gross_amount=>897500, :tax=>147500, :hotel_fees=>0, :base_fare=>750000, :currency=>"INR"}, {:amount=>1006500, :gross_amount=>1006500, :tax=>156500, :hotel_fees=>0, :base_fare=>850000, :currency=>"INR"}]

Now I want to return something like this:

{:amount=>952000, :gross_amount=>952000, :tax=>152000, :hotel_fees=>0, :base_fare=>800000, :currency=>"INR"}

where values are the average of values from each hash with same key.

Is there a simple way to do this. I have tried using merge but currency becomes 0 with it.

My attempt:

p[0].merge(p[1]){|k,v1,v2| (v1+v2)/2 unless v1 && v2 == "INR"}

Edit:

Actually my problem didn't end here, so after getting the average I needed to insert the values inside another hash. So I used something like this:

        price_array = offer_values.map do |v| 
          v.inject do |k, v| 
            k.merge!(price: k[:price].merge(v[:price]){|_, a, b| [a, b].flatten })
          end
        end
        price_array.map do |o|
          o[:price] = {}.tap{ |h| o[:price].each {|k, list| h[k] = list.all?{|e| [Fixnum, NilClass].include? e.class} ? list.map(&:to_i).sum/list.size : list.compact.first ; h  } }
        end

Where offer_array is the one with my orginal/first array in separate hashes. This I have tried for with 2 and 3 hashes and it is working.

If you guys have any suggestion on improving the code, It am open.

like image 872
Ravi Avatar asked Feb 04 '23 06:02

Ravi


1 Answers

The accepted answer will not work for more than 2 hashes, since merge works only 2 by 2 and you are calculating average here.

(((3 + 2) / 2) + 2.5) / 2 is different from (3 + 2 + 2.5) / 3

So I wrote a piece of code that could do what you want for whatever size of array you have

  def self.merge_all_and_average(array)
    new_hash = {}
    unless array.empty?
      array[0].keys.each do |key|
        if array[0][key].class == Fixnum
          total = array.map { |i| i[key] }.inject(0) { |sum, x| sum + x }
          new_hash = new_hash.merge(key => total / array.size)
        else
          new_hash = new_hash.merge(key => array[0][key])
        end
      end
    end
    new_hash
  end
like image 118
Ramon Marques Avatar answered Feb 16 '23 00:02

Ramon Marques