Home>

Thanks for your understanding.
I want to make a and b into an array of c as follows.

a = [{index: 1, kingaku +: 100},
     {index: 2, kingaku +: 200},
     {index: 3, kingaku +: 300}]
b = [{index: 1, kingaku-: 50},
     {index: 3, kingaku-: 50}]
c = [{index: 1, kingaku +: 100, kingaku-: 50, kingakudif: 50},
     {index: 2, kingaku +: 200, kingaku-: 0, kingakudif: 200},
     {index: 3, kingaku +: 300, kingaku-: 50, kingakudif: 250}]

As a method to come up with, it is a logic that turns around a and makes a muddy calculation, but I asked if I could use the method of rails etc. to apply it cleanly.
I want you to teach me.

RubyonRails5

  • Answer # 1

    a_plus = [
      {index: 1, 'kingaku +' =>100},
      {index: 2, 'kingaku +' =>200},
      {index: 3, 'kingaku +' =>300}
    ] .map {| item | [item [: index], item ['kingaku +']]. to_h
    b_minus = [
      {index: 1, 'kingaku-' =>50},
      {index: 3, 'kingaku-' =>50}
    ] .map {| item | [item [: index], item ['kingaku-']]. to_h
    [a_plus.keys + b_minus.keys] .uniq.map do | index |
      plus = a_plus [index] .presence || 0 #Standard syntax that will be 0 if it exists, 0 if not
      minus = b_minus [index] .presence || 0
      {index: index, kingaku_plus: plus, kingaku_minus: minus, kingaku_dif: plus- minus}
    end

    I do n’t like this.
    The point is Hash by map.to_h
    Hash is easy to use because of its fast access speed. Check it yourself.

    Do not mix the + and-signs with the hash key. It is bothersome and uncomfortable.

  • Answer # 2

    If you use rails, you can useEnumarable # index_by (&)from ActiveSupport.
    Because it is easy to understand and expandable, it may be slow.

    ax = a.index_by {| ia | ia [: index]}
    bx = b.index_by {| ib | ib [: index]}
    items = ax.merge (bx) do | _, ia, ib |
      i = ia.merge (ib)
      i [: 'kingaku +'] || = 0
      i [: 'kingaku-'] || = 0
      i [: kingakudif] = i [: 'kingaku +']-i [: 'kingaku-']
      i
    end.values ​​

    It's a digression, but since this kind of processing is rather an RDB specialty,
    I feel like it's better to use the DB layer for Rails.

  • Answer # 3

    I'm muddy but I wrote something that works.
    calc.rb

    def sub_total (rec, attr)
      adds = rec ["# {attr} +"] == nil? 0: rec ["# {attr} +"]. sum
      subs = rec ["# {attr}-"] == nil? 0: rec ["# {attr}-"]. sum
      {"# {attr} +" =>adds, "# {attr}-" =>subs, "# {attr} dif" =>adds-subs}
    end
    def total (a, b, attr)
      ab = (a + b) .each_with_object ({}) do | rec, mem |
        idx = rec.delete (: index)
        rec.each do | kind, val |
          mem [idx] = {} if mem [idx] == nil
          mem [idx] [kind] = [] if mem [idx] [kind] == nil
          mem [idx] [kind] + = [val]
        end
      end
      # p "ab"
      # p ab
      ab.each_with_object ([]) do | (idx, rec), mem |
        mem<<{index: idx} .merge (sub_total (rec, attr))
      end
    end
    a = [
      {index: 1, 'kingaku +' =>100},
      {index: 2, 'kingaku +' =>200},
      {index: 3, 'kingaku +' =>300}
    ]
    b = [
      {index: 1, 'kingaku-' =>50},
      {index: 3, 'kingaku-' =>50}
    ]
    p total (a, b, 'kingaku')

    Execution result