簡體   English   中英

哈希初始化的Ruby哈希

[英]Ruby hash of hash initialization

考慮@data是ActiveRecords的數組,其字段為dateclassnamegrade 假設我想以兩個哈希結束,一個是每個名稱中所有日期的唯一集合; 另一個按班級細分,然后按日期,然后按名稱顯示成績。

dates  = {}
grades = {}

@data.each do |d|
   dates[ d.name ][ d.date ] = ''                              # 1
   grades[ d.class => { d.date => { d.name => d.grade } } ]    # 2 
end
  1. 導致錯誤:

    未定義的方法[[] ='for nil:NilClass

    dates[ d.name => { d.date => '' } ]僅存儲最后一條記錄(不會合並到較早的結果中)

  2. 不會出錯,但以空哈希{}結尾

回到Perl之后,我忘記了如何在Ruby中初始化和添加到哈希哈希中。


更新

對於第一個( 日期 ),看起來我可以在循環內執行以下操作:

dates[ d.name ] ||= { d.date => '' }
dates[ d.name ][ d.date ] = ''

查看文檔,我不知道這是否是正確的方法,它似乎效率也不高,因為它將對第一個值進行兩次賦值。 它還建議對於每個鍵,我都需要聲明/初始化基礎數據結構,隨着哈希值的散列值(如等級散列值)的增加,該數據結構將變得冗長。


資源:

[{ name: 'greg', class:'science', date:'jan', grade:'a' },
 { name: 'greg', class:'math'   , date:'jan', grade:'b' },
 { name: 'barb', class:'history', date:'jan', grade:'a' },
 { name: 'barb', class:'science', date:'feb', grade:'c' }]

日期看起來像:

{ 'greg' => { 'jan' => '' },
  'barb' => { 'jan' => '' ,
              'feb' => '' 
            }
}

成績看起來像:

{ 'science' => { 'jan' => { 'greg' => 'a' } ,
                 'feb' => { 'barb' => 'c' } },
  'math'    => { 'jan' => { 'greg' => 'b' } },
  'history' => { 'jan' => { 'barb' => 'a' } }
}

這實際上可以正常工作,因為當您嘗試從哈希訪問密鑰時,它不僅返回默認值,還對其進行設置:

Hash.new do |h, k|
  h[k] = Hash.new do |hh, kk|
    hh[kk] = {}
  end
end

更新:

盡管對於未來的開發人員而言,可能比僅檢查是否為nil更混亂,但這可能會更清潔一點。

dates = Hash.new { |hash, key| hash[key] = {} }
grades = Hash.new { |hash, key| hash[key] = dates.clone }

嘗試:

d={}
c=Client.first
d[c.last_name]=[]
d[c.last_name][c.id]=//your value

d [c.last_name] = [],為c.last_name初始化一個哈希數組

我能夠像這樣構建日期哈希:

arr = [{ name: 'greg', class:'science', date:'jan', grade:'a' },
       { name: 'greg', class:'math'   , date:'jan', grade:'b' },
       { name: 'barb', class:'history', date:'jan', grade:'a' },
       { name: 'barb', class:'science', date:'feb', grade:'c' }]


dates = arr.group_by { |x| x[:name] }.each_with_object({}) do |(k, v), hash|
  dates = v.map { |i| i[:date] }.uniq
  dates_hash = dates.each_with_object({}) { |date, h| h[date] = "" }
  hash[k] = dates_hash
end

puts dates

{"greg"=>{"jan"=>""}, "barb"=>{"jan"=>"", "feb"=>""}}

要獲取每個:name的唯一:date值,您可以使用Hash.update的形式(與merge!相同),該形式使用哈希確定鍵的值包含在要合並的兩個哈希中:

def dates_by_name(arr)
  arr.each_with_object({}) { |g,h|
    h.update({g[:name]=>[g[:date]]}) {|_,ov,nv|
      ov.include?(nv.first) ? ov : ov + nv}}
end

有許多方法可以按班級,日期和名稱來組織成績等級。 以下采用遞歸:

def grade_by_class_date_name(arr, fields)
  fd = fields.dup
  f = fd.shift
  return arr.first[:grade] if f==:grade
  g = arr.each_with_object(Hash.new { |h,k| h[k] = [] }) { |e,g|
    g[e[f]] << e.reject { |k,_| k == f } }
  g.each_key { |k| g[k] = grade_by_class_date_name(g[k], fd) }
  g 
end          

例子

arr = [{ name: 'greg', class:'science', date:'jan', grade:'a' },
       { name: 'greg', class:'math'   , date:'jan', grade:'b' },
       { name: 'barb', class:'history', date:'jan', grade:'a' },
       { name: 'barb', class:'science', date:'feb', grade:'c' }]

dates_by_name(arr)
  #=> {"greg"=>["jan"], "barb"=>["jan", "feb"]} 

dates_by_name返回的哈希值不是您要求的格式,但是您可以輕松地對其進行操作以滿足您的要求。

fields = [:class, :date, :name, :grade] 

grade_by_class_date_name(arr, fields)
  #=> {"science"=>{"jan"=>{"greg"=>"a"},
  #                "feb"=>{"barb"=>"c"}},
  #    "math"   =>{"jan"=>{"greg"=>"b"}},
  #    "history"=>{"jan"=>{"barb"=>"a"}}} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM