Search code examples
rubycomparedistinct-values

ruby - transform_value of a specific key[1]


I am trying for each row to compare the fx value of each corresponding name; So the outcome should be : diff={"name"=>"XPT", "fx"=>"1.1315313597682419"} or rounded before having to be compared _ if it is easier to get it that way : diff={"name"=>"XPT", "fx"=>"1.13153"}

So far I have a TypeError (no implicit conversion of String into Integer) with the following:

def compare_values
    diff = {}
    a = [{"src"=>"reportStack"},
    {"name"=>"XPT", "fx"=>"1.1315313597682419"},
    {"name"=>"XAU", "fx"=>"27.0165670831070071"},
    {"name"=>"XAG", "fx"=>"8.4192241535397429"}]

    b = [{"src"=>"reportOverflow"},
    {"name"=>"XPT", "fx"=>"1.13163"},
    {"name"=>"XAU", "fx"=>"27.0165670831070071"},
    {"name"=>"XAG", "fx"=>"8.4192"}]

    b.each do |b_row|
       a.each do |a_row|
          b.each do |k,v|
            diff = k if a_row['name'].value == e_row['name'].value && a_row['fx'].value.to_f != a_row['fx'].value.to_f
          end
      end
    end
end

Could anyone please give a tip how to handle this pickle?


Solution

  • I would begin by simplifying the data structures for both reportStack (a) and reportOverflow (b) into hashes, where the key is name, and the value is fx. This will allow us to compare key-value pairs without having to iterate through an array and checking each value.

    report_stack = a.inject(Hash.new) do |memo, report_stack_entry|
      next memo unless report_stack_entry['name']
    
      memo[report_stack_entry['name']] = report_stack_entry['fx']
      memo
    end
    
    # report_stack => {"XPT"=>"1.1315313597682419", "XAU"=>"27.0165670831070071", "XAG"=>"8.4192241535397429"}
    
    report_overflow = b.inject(Hash.new) do |memo, report_overflow_entry|
      next memo unless report_overflow_entry['name']
    
      memo[report_overflow_entry['name']] = report_overflow_entry['fx']
      memo
    end
    
    # report_overflow => {"XPT"=>"1.13163", "XAU"=>"27.0165670831070071", "XAG"=>"8.4192"}
    

    I would then .reject over report_stack with a !nil?, start_with?, and == condition on the corresponding report_overflow key

    diff = report_stack.reject do |name, fx|
      overflow_fx = report_overflow[name]
    
      !overflow_fx.nil? && (
        fx == overflow_fx ||
        fx.start_with?(overflow_fx)
      )
    end
    
    diff #=> {"XPT"=>"1.1315313597682419"}
    

    If any additional comparison logic is required, you should be able to easily update the condition in the .reject block to do so.