以下哈希是否更容易转置?我有一个有效的解决方案,但转置方法很难阅读。用例是作业的散列(j1,j2,j3等)以及它们出现的日期(d1,d2,d3等等)。要求是采用按日期然后作业分组的事件(e1,e2,e3等等)的哈希值,并将它们转换为按作业然后日期分组的事件
我尝试使用#zip方法但是需要在j1:d1处注入nil,然后将它们从结果中删除。我也很难找到带有块参数的#zip的示例用法。我理解#zip with a block always returns nil但是因此我无法理解你将如何实际使用它。
require 'rspec'
require 'pry'
# | d1 | d2 | d3 |
# ----------------------
# j1 | | e2 | e3 |
# --------------------------
# j2 | e4 | e5 | e6 |
# --------------------------
# j3 | e7 | | e9 |
# --------------------------
def transpose(h)
Hash[
dates(h).map do |d|
[
d,
Hash[ h.keys.map do |j|
h[j][d] ? [j, h[j][d]] : nil
end.compact ]
]
end
]
end
def dates(h)
h.values.map(&:keys).reduce(:|).sort
end
describe "transpose" do
let(:starting) {
{
j1: { d2: :e2, d3: :e3 },
j2: { d1: :e4, d2: :e5, d3: :e6 },
j3: { d1: :e7, d3: :e9 }
}
}
let(:transposed) {
{
d1: { j2: :e4, j3: :e7 },
d2: { j1: :e2, j2: :e5 },
d3: { j1: :e3, j2: :e6, j3: :e9 }
}
}
it { expect(dates(starting)).to eq([:d1, :d2, :d3]) }
it { expect(transpose(starting)).to eq(transposed) }
end
答案 0 :(得分:2)
我已经重写了你的transpose
方法,它应该更快更干净:
def transpose(h)
h.each_with_object({}) do |(outer, data), ret|
data.each do |inner, event|
ret[inner] = {} unless ret[inner]
ret[inner][outer] = event
end
end
end
它没有使用不必要的日期映射,并且两种方式都有效(更改内部和外部键)。让我知道你的想法:)。