考虑@data是一个ActiveRecords数组,其字段为 date , class , name 和 grade 。假设我想得到两个哈希值,一个是每个名字的所有日期的唯一集合;另一个按类分类,然后是日期,然后命名以显示等级。
dates = {}
grades = {}
@data.each do |d|
dates[ d.name ][ d.date ] = '' # 1
grades[ d.class => { d.date => { d.name => d.grade } } ] # 2
end
导致错误:
未定义的方法`[] ='为nil:NilClass
dates[ d.name => { d.date => '' } ]
仅存储最后一条记录(不会合并到较旧的结果中)
没有错误,但以空哈希{}
回到Perl之后,我忘记了如何初始化并添加到Ruby中哈希的散列。
对于第一个( date ),看起来我可以在循环中执行以下操作:
dates[ d.name ] ||= { d.date => '' }
dates[ d.name ][ d.date ] = ''
查看文档,我不知道这是否是正确的方法,它似乎效率低下,因为它将为第一个值执行两次赋值。它还建议对于每个键,我需要声明/初始化底层数据结构,哈希散列的深度越长(如 grade 哈希)。
来源:
[{ 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' } }
}
答案 0 :(得分:0)
这实际上会起作用,因为当您尝试从散列中访问密钥时,它不仅会返回默认值,还会设置它:
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 }
答案 1 :(得分:0)
尝试:
d={}
c=Client.first
d[c.last_name]=[]
d[c.last_name][c.id]=//your value
d [c.last_name] = [],初始化c.last_name
的哈希数组答案 2 :(得分:0)
我能够像这样构建日期哈希:
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"=>""}}
答案 3 :(得分:0)
<强>代码强>
要获取每个:date
的唯一:name
值,您可以使用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"}}}