转向的最佳(最佳效果)方式是什么:
csv_data = [
{'id' => 1, 'foo_1' => 'a', 'bar_1' => 'b', 'foo_2' => 'c', 'bar_2' => 'd'},
{'id' => 2, 'foo_1' => 'e', 'bar_1' => 'f', 'foo_2' => 'g', 'bar_2' => 'h'}
]
到
records = [
{'id' => 1, 'foo' => 'a', 'bar' => 'b'},
{'id' => 1, 'foo' => 'c', 'bar' => 'd'},
{'id' => 2, 'foo' => 'e', 'bar' => 'f'},
{'id' => 2, 'foo' => 'g', 'bar' => 'h'}
]
澄清:foo_100可能会有foo_1,但它会有所不同。
答案 0 :(得分:1)
如果你总是使用长度为2的相同键,你可以写:
records = csv_data.flat_map do |row|
[
{id: row["id"], foo: row["foo_1"], bar: row["bar_1"]},
{id: row["id"], foo: row["foo_2"], bar: row["bar_2"]},
]
end
适用于任何字段和长度的更通用的算法。我会在每一步添加数据,这可能会有所帮助:
records = csv_data.flat_map do |row|
row
# {"id"=>1, "foo_1"=>"a", "bar_1"=>"b", "foo_2"=>"c", "bar_2"=>"d"}
.reject { |key, value| key == "id" }
# {"foo_1"=>"a", "bar_1"=>"b", "foo_2"=>"c", "bar_2"=>"d"}
.group_by { |key, value| key.split("_")[0] }
# {"foo"=>[["foo_1", "a"], ["foo_2", "c"]], "bar"=>[["bar_1", "b"], ["bar_2", "d"]]}
.map { |tag, key_values| [tag].product(key_values.map(&:last)) }
# [[["foo", "a"], ["foo", "c"]], [["bar", "b"], ["bar", "d"]]]
.transpose
# [[["foo", "a"], ["bar", "b"]], [["foo", "c"], ["bar", "d"]]]
.map { |pairs| {"id" => row["id"]}.merge(pairs.to_h) }
# [{"id"=>1, "foo"=>"a", "bar"=>"b"}, {"id"=>1, "foo"=>"c", "bar"=>"d"}]
end