我有几天遇到麻烦,我需要帮助来解决它。 我有一个哈希,它具有相同键的多个值:
{"answers":
[
{"id":1,"value":true},
{"id":3,"value":false},
{"id":2,"value":3},
{"id":1,"value":false},
{"id":2,"value":false},
{"id":2,"value":1}
]
}
我想要一种方法来对一个键的所有值进行分组,例如:
{
"answers": [
{
"id":1, "value": [true, false]
},
{
"id":3, "value": [false]
},
{
"id":2, "value":[3, false, 1]
}
]
}
我尝试过使用reduce方法,但是我找不到将值链接到键的方法。 任何人都可以帮助我吗? 谢谢!
答案 0 :(得分:2)
看起来您希望Enumerable#group_by
通过每个哈希中的:id
键重新组合哈希数组。
此方法获取answers数组并返回一个新的,已转换的答案数组:
def transform_answers(answers)
answers
.group_by { |h| h[:id] }
.each_value { |a| a.map! { |h| h[:value] } }
.map { |id, value| { id: id, value: value } }
end
你可以像这样使用它:
hash = {
answers: [
{ id: 1, value: true },
{ id: 1, value: false },
{ id: 2, value: 3 },
{ id: 2, value: false },
{ id: 2, value: 1 },
{ id: 3, value: false }
]
}
transformed_answers = transform_answers(hash[:answers]) # => [{:id=>1, :value=>[true, false]}, {:id=>2, :value=>[3, false, 1]}, {:id=>3, :value=>[false]}]
您可以轻松获取已转换的答案并将其放回类似于原始输入的哈希值:
transformed_hash = { answers: transformed_answers }
答案 1 :(得分:1)
hash = {
answers: [
{ id: 1, value: true },
{ id: 1, value: false },
{ id: 2, value: 3 },
{ id: 2, value: false },
{ id: 2, value: 1 },
{ id: 3, value: false }
]
}
def doit(answers)
answers.each_with_object({}) do |g,h|
h.update(g[:id]=>{ id: g[:id], value: [g[:value]] }) do |_,o,n|
{ id: o[:id], value: o[:value]+n[:value] }
end
end.values
end
{ answers: doit(hash[:answers]) }
#=> {:answers=>[
# {:id=>1, :value=>[true, false]},
# {:id=>2, :value=>[3, false, 1]},
# {:id=>3, :value=>[false]}
# ]
# }
这使用Hash#update(aka merge!
)的形式,它使用一个块来确定合并的两个哈希中存在的键的值。该块是
do |_k,o,n|
{ id: o[:id], value: o[:value]+n[:value] }
end
有关三个块变量的定义,请参阅update
的文档,_k
,o
和n
。我编写了第一个块变量(公共密钥)_k
,而不是k
,以表示它未在块计算中使用。
请注意,在values
中执行doit
之前,该方法构造了以下哈希值。
{1=>{:id=>1, :value=>[true, false]},
2=>{:id=>2, :value=>[3, false, 1]},
3=>{:id=>3, :value=>[false]}}