Arrays 按数字键的Ruby组哈希数组
我得到了一个哈希数组,如下所示:Arrays 按数字键的Ruby组哈希数组,arrays,ruby,hash,Arrays,Ruby,Hash,我得到了一个哈希数组,如下所示: [{1=>6}, {1=>5}, {4=>1}] 我试着按键分组 因此,使用命名键的解决方案类似于:group_by{h | h['keyName']} 如何使用短Lambda表达式或group_获得以下数组: [{1=>[5, 6], 4=>[1]}] 编辑-解释我试图实现的目标: 我有一个数据库可以给学生分配课程。 每个学生每年都可以为一门课程投票 投票结果如下: Vote(id: integer, first: integ
[{1=>6}, {1=>5}, {4=>1}]
我试着按键分组
因此,使用命名键的解决方案类似于:group_by{h | h['keyName']}
如何使用短Lambda表达式或group_获得以下数组:
[{1=>[5, 6], 4=>[1]}]
编辑-解释我试图实现的目标:
我有一个数据库可以给学生分配课程。
每个学生每年都可以为一门课程投票
投票结果如下:
Vote(id: integer, first: integer, second: integer, active: boolean,
student_id: integer, course_id: integer, year_id: integer,
created_at: datetime, updated_at: datetime)
{1=>[1, 1], 4=>[4]}
Year.get_active_year.votes.order(:first).map{|c| {c.first=> c.student_id}}
现在,如果课程没有超员,我想自动将学生分配到课程中。为了了解每门课程有多少学生投票,我首先尝试了以下方法:
Year.get_active_year.votes.order(:first).map(&:first).group_by(&:itself)
结果如下所示:
Vote(id: integer, first: integer, second: integer, active: boolean,
student_id: integer, course_id: integer, year_id: integer,
created_at: datetime, updated_at: datetime)
{1=>[1, 1], 4=>[4]}
Year.get_active_year.votes.order(:first).map{|c| {c.first=> c.student_id}}
现在我可以使用。每个功能:
Year.get_active_year.votes.order(:first).map(&:first).group_by(&:itself).each do |_key, value|
if Year.get_active_year.courses.where(number: _key).first.max_visitor >= value.count
end
end
每门课程都有一个明确的数字,学生只需使用课程编号进行投票
但如果我做了所有这些,我就失去了学生投票支持那门课程的信息,所以我试着像这样保存这些信息:
Vote(id: integer, first: integer, second: integer, active: boolean,
student_id: integer, course_id: integer, year_id: integer,
created_at: datetime, updated_at: datetime)
{1=>[1, 1], 4=>[4]}
Year.get_active_year.votes.order(:first).map{|c| {c.first=> c.student_id}}
def组_值(arr)
arr.reduce(Hash.new{| h,k | h[k]=[])do | memo,h|
h、 每个{k,v{memo[k]6},{1=>5},{4=>1}]
组_值(xs)#=>{1=>[6,5],4=>[1]}
请注意,当哈希包含多个条目时,此解决方案也有效:
ys=[{1=>6,4=>2},{1=>5},{4=>1}]
组_值(ys)#=>{1=>[6,5],4=>[2,1]}
使用#group#u by
实现此目的的一种方法是按每个散列的第一个键进行分组,然后将结果映射到#map
以返回相应的值:
arr = [{1=>6}, {1=>5}, {4=>1}]
arr.group_by {|h| h.keys.first}.map {|k, v| {k => v.map {|h| h.values.first}}}
# => [{1=>[6, 5], 4=>[1]}]
希望这有帮助 注入到默认哈希中:
arr = [{1=>6}, {1=>5}, {4=>1}]
arr.inject(Hash.new{|h,k| h[k]=[]}){|h, e| h[e.first[0]] << e.first[1]; h}
# => {1=>[6, 5], 4=>[1]}
arr=[{1=>6},{1=>5},{4=>1}]
arr.inject(Hash.new{h,k{h[k]=[]}){h,e{h[e.first[0]]{1=>[6,5],4=>[1]}
或者,如评论中所建议的:
arr.each.with_object(Hash.new{|h, k| h[k] = []}){|e, h| h[e.first[0]] << e.first[1]}
# => {1=>[6, 5], 4=>[1]}
arr.each.with_object(Hash.new{h,k{h[k]=[]){e,h{h[e.first[0]]{1=>[6,5],4=>[1]}
步骤如下
a = arr.flat_map(&:to_a)
#=> [[1, 6], [1, 5], [4, 1]]
b = a.group_by(&:first)
#=> {1=>[[1, 6], [1, 5]], 4=>[[4, 1]]}
b.transform_values { |arr| arr.transpose.last }
#=> {1=>[6, 5], 4=>[1]}
注意
b.transform_values { |arr| arr.transpose }
#=> {1=>[[1, 1], [6, 5]], 4=>[[4], [1]]}
和arr.flat\u映射(&:to\u a)
可以替换为arr.map(&:flatte)
另一种方式:
arr.each_with_object({}) do |g,h|
k,v = g.flatten
h.update(k=>[v]) { |_,o,n| o+n }
end
#=> {1=>[6, 5], 4=>[1]}
它使用(aka
merge!
)的形式,使用块{|,o,n | o+n}
来确定合并的两个哈希中存在的键的值。块变量
是公共键(用下划线表示,表示它在块计算中未使用).变量o
和n
分别是合并的两个哈希中的公共键的值。这听起来像是一个…你想实现什么?你尝试了什么?你到底是如何发现自己与一组哈希一起的?为什么你更喜欢[{1=>[5,6]},{4=>[1]}
而不是{1=>[5,6],4=>[1]}
?这太不寻常了,可能很糟糕了,到目前为止,三个答案中有两个甚至没有注意到他们没有按照你的要求去做(投票人也没有注意到)。哦,等等,更正,这三个答案都“错了”。什么是“命名键”和“未命名键”?