Ruby 获取现有散列的键并为其提供默认值

Ruby 获取现有散列的键并为其提供默认值,ruby,hash,fetch,Ruby,Hash,Fetch,给定一个现有哈希,例如: { "April_data" : { "April" : 10, "May" : 8, "June" : 7, "July" : 7, "August" : 5, "September" : 2 }, "May_data" : { "May" : 4, "June" : 3, "July" : 2, "August" : 2, "September" : 0 },

给定一个现有哈希,例如:

{
  "April_data" : {
    "April" : 10,
    "May" : 8,
    "June" : 7,
    "July" : 7,
    "August" : 5,
    "September" : 2
  },
  "May_data" : {
    "May" : 4,
    "June" : 3,
    "July" : 2,
    "August" : 2,
    "September" : 0
  },
  "June_data" : {
    "June" : 12,
    "July" : 12,
    "August" : 8,
    "September" : 2
  }
}
如何在其他月份保留“April_data”中包含的所有键,并分配默认值,如“0”?因此,结果如下所示:

{
  "April_data" : {
    "April" : 10,
    "May" : 8,
    "June" : 7,
    "July" : 7,
    "August" : 5,
    "September" : 2
  },
  "May_data" : {
    "April": 0,
    "May" : 4,
    "June" : 3,
    "July" : 2,
    "August" : 2,
    "September" : 0
  },
  "June_data" : {
    "April": 0,
    "May": 0,
    "June" : 12,
    "July" : 12,
    "August" : 8,
    "September" : 2
  }
}

任何特别的帮助

诀窍是记住哈希将覆盖现有密钥,因此从默认密钥开始,并将它们覆盖到您想要保留的密钥:

stub = hash.each_with_object({}) do |(_, v), memo|
  memo.merge!(v)
end.map { |k, v| [k, 0] } # or end.keys.product([0]).to_h
   .to_h
#⇒ {"April"=>0, "May"=>0, "June"=>0, "July"=>0, "August"=>0, "September"=>0}

hash.map { |k, v| [k, stub.merge(v)] }.to_h
#⇒ desired result
DEFAULTS = {
  "April" => 0,
  "May" => 0,
  "June" => 0,
  "July" => 0,
  "August" => 0,
  "September" => 0
}

data = {
  "April_data" => {
    "April" => 10,
    "May" => 8,
    "June" => 7,
    "July" => 7,
    "August" => 5,
    "September" => 2
  },
  "May_data" => {
    "May" => 4,
    "June" => 3,
    "July" => 2,
    "August" => 2,
    "September" => 0
  },
  "June_data" => {
    "June" => 12,
    "July" => 12,
    "August" => 8,
    "September" => 2
  }
}

data.each do |k, v|
  data[k] = DEFAULTS.merge(v)
end
其结果是:

require 'ap'
ap data

# >> {
# >>   "April_data" => {
# >>     "April"     => 10,
# >>     "May"       => 8,
# >>     "June"      => 7,
# >>     "July"      => 7,
# >>     "August"    => 5,
# >>     "September" => 2
# >>   },
# >>   "May_data"   => {
# >>     "April"     => 0,
# >>     "May"       => 4,
# >>     "June"      => 3,
# >>     "July"      => 2,
# >>     "August"    => 2,
# >>     "September" => 0
# >>   },
# >>   "June_data"  => {
# >>     "April"     => 0,
# >>     "May"       => 0,
# >>     "June"      => 12,
# >>     "July"      => 12,
# >>     "August"    => 8,
# >>     "September" => 2
# >>   }
# >> }
如果您不确定键应该是什么,或者,如果您像我一样懒惰,想让Ruby为您定义默认值,您可以扫描子哈希并让Ruby解决:

DEFAULTS = data.flat_map{ |k, v| v.keys}.uniq.map{ |k| [k, 0] }.to_h
# => {"April"=>0, "May"=>0, "June"=>0, "July"=>0, "August"=>0, "September"=>0}
这就是它所做的:

DEFAULTS = data
          .flat_map{ |k, v| v.keys} # => ["April", "May", "June", "July", "August", "September", "May", "June", "July", "August", "September", "June", "July", "August", "September"]
          .uniq # => ["April", "May", "June", "July", "August", "September"]
          .map{ |k| [k, 0] } # => [["April", 0], ["May", 0], ["June", 0], ["July", 0], ["August", 0], ["September", 0]]
          .to_h
# => {"April"=>0, "May"=>0, "June"=>0, "July"=>0, "August"=>0, "September"=>0}
或者,但不一定更快或更简洁:

DEFAULTS = data.values # => [{"April"=>10, "May"=>8, "June"=>7, "July"=>7, "August"=>5, "September"=>2}, {"May"=>4, "June"=>3, "July"=>2, "August"=>2, "September"=>0}, {"June"=>12, "July"=>12, "August"=>8, "September"=>2}]
               .flat_map(&:keys) # => ["April", "May", "June", "July", "August", "September", "May", "June", "July", "August", "September", "June", "July", "August", "September"]
               .uniq # => ["April", "May", "June", "July", "August", "September"]
               .map{ |k| [k, 0] }.to_h  # => {"April"=>0, "May"=>0, "June"=>0, "July"=>0, "August"=>0, "September"=>0}

欢迎来到堆栈溢出。请阅读,包括链接页面,和。同样适用。我们想知道你为解决这个问题付出了什么样的努力。你是否搜索过网站却没有找到答案?如果是,这些页面在哪里以及如何未能回答问题?你写代码了吗?若否,原因为何?如果是这样,说明问题的最小示例在哪里?如果没有这一点,看起来您希望我们为您编写代码。