我想根据数据库查询的结果创建一个哈希,使其键是除最后一个列之外的列值,并且该值是最后一列值(或默认值)。例如,如果我有行:
1 2 3 1
1 2 4 9
1 3 2 nil
和默认值111
,我应该得到:
{
1 =>
{
2 => { 3 => 1, 4 => 9},
3 => { 2 => 111}
}
}
我想让方法足够通用以处理任意数量的列,因此签名可以是:
to_lookup(rows, default_value, value_column, *columns)
我该怎么做?
更新:忘记了输出中的逗号。
答案 0 :(得分:3)
[编辑:看完@ cthulhu&#39的回答后,我想我可能误解了这个问题。我假设将连续的行分组,而不是所有要分组的行。我将为前一种解释留下我的答案。]
我相信这就是你要找的东西:
def hashify(arr)
return arr.first.first if arr.first.size == 1
arr.slice_when { |f,s| f.first != s.first }.
each_with_object({}) do |a,h|
key, *rest = a.transpose
h[key.first] = hashify(rest.transpose)
end
end
hashify [[1, 2, 3, 1], [1, 2, 4, 9], [1, 3, 2, nil]]
#=> {1=>{2=>{3=>1, 4=>9}, 3=>{2=>nil}}}
hashify [[1, 2, 3, 1], [1, 2, 4, 9], [2, 3, 2, nil]]
#=> {1=>{2=>{3=>1, 4=>9}}, 2=>{3=>{2=>nil}}}
使用默认值替换nil
可以在构造哈希之前或之后完成。
Enumerable#slice_when在v2.2中被赋予了我们。对于早期版本,您可以替换:
arr.slice_when { |f,s| f.first != s.first }
与
arr.chunk { |row| row.first }.map(&:last)
答案 1 :(得分:2)
我通过删除传递默认值的能力简化了事情, 我还简化了签名方法只有一个参数。
RSpec.describe "#to_lookup" do
def to_lookup(rows)
return rows.first.first if rows.flatten.size == 1
h = {}
rows.group_by { |e| e.first }.each_entry do |k, v|
v.each &:shift
h[k] = to_lookup(v)
end
h
end
let :input do
[
[1, 2, 3, 1],
[1, 2, 4, 9],
[1, 3, 2, 111],
]
end
let :output do
{
1 => {
2 => {3 => 1, 4 => 9},
3 => {2 => 111}
}
}
end
it { expect(to_lookup(input)).to eq(output) }
end
顺便说一下我想知道你想要输出什么输出:
1 2 3 1
1 2 3 2
编辑:工作代码段:http://rubysandbox.com/#/snippet/566aefa80195f1000c000000