Ruby merge hash value

2019-09-14 17:06发布

I've written an API to organize my daily user data.

The origin format is like

"dau": {
      "2017-05-02": 1,
      "2017-05-04": 2,
      "2017-05-05": 2,
      }

"new_user": {
      "2017-05-02": 1,
      "2017-05-04": 0,
      "2017-05-07": 0,
}

It's hard to display in HTML table row by row.

Therefore, I want the format to become this one.

However, I have no idea how to deal with.

info: {
      "2017-05-02": {
            dau: 1,
            new_user: 1
      },
      "2017-05-04": {
            dau: 2,
            new_user: 0
      },
      "2017-05-05": {
            dau: 2
      },
      "2017-05-07": {
            new_user: 0
      }
}

3条回答
爷、活的狠高调
2楼-- · 2019-09-14 17:21
keys = (dau.keys + new_user.keys).uniq 
# [:"2017-05-02", :"2017-05-04", :"2017-05-05", :"2017-05-07"]

keys.each_with_object({}) do |key, result| 
  result[key] = {dau: dau[key], new_user: new_user[key] }.compact
end
# {:"2017-05-02"=>{:dau=>1, :new_user=>1},
# :"2017-05-04"=>{:dau=>2, :new_user=>0},
# :"2017-05-05"=>{:dau=>2},
# :"2017-05-07"=>{:new_user=>0}}
查看更多
神经病院院长
3楼-- · 2019-09-14 17:25

suppose you have data, then

(data['dau'].keys + data['new_user'].keys).uniq.map { |k| [k, { dau: data['dau'][k].to_i, new_user: data['new_user'][k].to_i } ] }.to_h

and if you don't want default/0 values then,

(data['dau'].keys + data['new_user'].keys).uniq.map { |k| [k, { dau: data['dau'][k], new_user: data['new_user'][k] }.compact ] }.to_h

Output:

{
    "2017-05-02" => {
            :dau => 1,
        :new_user => 1
    },
    "2017-05-04" => {
            :dau => 2,
        :new_user => 0
    },
    "2017-05-05" => {
        :dau => 2
    },
    "2017-05-07" => {
        :new_user => 0
    }
}

Hope it helps..

查看更多
小情绪 Triste *
4楼-- · 2019-09-14 17:34

Here's an alternative with each_with_object. It should work with any number of keys:

data = {"dau": {
  "2017-05-02": 1,
  "2017-05-04": 2,
  "2017-05-05": 2
  },
"new_user": {
  "2017-05-02": 1,
  "2017-05-04": 0,
  "2017-05-07": 0
  }
}


info = Hash.new { |h, k| h[k] = {} }
info = data.each_with_object(info) do |(key, sub_h), h|
  sub_h.each do |date, i|
    h[date][key] = i
  end
end

p info
# {:"2017-05-02"=>{:dau=>1, :new_user=>1}, :"2017-05-04"=>{:dau=>2, :new_user=>0}, :"2017-05-05"=>{:dau=>2}, :"2017-05-07"=>{:new_user=>0}}
查看更多
登录 后发表回答