Ruby 的 CSV 哈希数组
Array of Hashes to CSV with Ruby
我正在使用哈希数组创建一个 CSV 订单文件。 CSV 输出中的 name 和 id 需要在每一行都相同,但每个订单的行数取决于订单中的 skus 数量。
有没有简单的方法输出这个订单数组?
orders = []
orders << { name:"bob", id:123, sku:[ "123a", "456b", "xyz1" ], qty:[ 2, 4, 1 ] }
orders << { name:"kat", id:987, sku:[ "456b", "aaa0", "xyz1" ], qty:[ 8, 9, 5 ] }
orders << { name:"kat", id:222, sku:[ "123a" ], qty:[ 4 ] }
像这样的 CSV 文件:
name,id,sku,qty
bob,123,123a,2
bob,123,456b,4
bob,123,xyz1,1
kat,987,456b,8
kat,987,aaa0,9
kat,987,xyz1,5
kat,222,123a,4
首先,让我们准备要转储为 CSV 的数组:
asarray = orders.map { |e|
[e[:name], e[:id], e[:sku].zip(e[:qty])]
}.map { |e|
e.last.map { |sq| [*e[0..1], *sq] }
}
现在我们准备好将原始数组序列化为 CSV:
require 'csv'
CSV.open("path/to/file.csv", "wb") do |csv|
csv << ["name", "id", "sku", "qty"]
asarray.each { |order|
order.each { |row|
csv << row
}
}
end
试试这个:
module SKUSeparator
def map_by_skus
inject([]) do |csv, order|
order[:sku].each_with_index do |sku, index|
csv << [order[:name], order[:id], order[:sku][index], order[:qty][index]]
end
csv
end
end
def to_csv
map_by_skus.map { |line| line.join(",") }.join("\n")
end
end
ORDERS = [
{:name=>"bob", :id=>123, :sku=>["123a", "456b", "xyz1"], :qty=>[2, 4, 1]},
{:name=>"kat", :id=>987, :sku=>["456b", "aaa0", "xyz1"], :qty=>[8, 9, 5]},
{:name=>"kat", :id=>222, :sku=>["123a"], :qty=>[4]}
]
ORDERS.extend(SKUSeparator).map_by_skus # =>
# [
# ["bob", 123, "123a", 2],
# ["bob", 123, "456b", 4],
# ["bob", 123, "xyz1", 1],
# ["kat", 987, "456b", 8],
# ["kat", 987, "aaa0", 9],
# ["kat", 987, "xyz1", 5],
# ["kat", 222, "123a", 4]
# ]
ORDERS.extend(SKUSeparator).to_csv # =>
# bob,123,123a,2
# bob,123,456b,4
# bob,123,xyz1,1
# kat,987,456b,8
# kat,987,aaa0,9
# kat,987,xyz1,5
# kat,222,123a,4
作为变体:
orders = []
orders << { name:"bob", id:123, sku:[ "123a", "456b", "xyz1" ], qty:[ 2, 4, 1 ] }
orders << { name:"kat", id:987, sku:[ "456b", "aaa0", "xyz1" ], qty:[ 8, 9, 5 ] }
orders << { name:"kat", id:222, sku:[ "123a" ], qty:[ 4 ] }
csv = ''
orders.each do |el|
el[:qty].length.times do |idx|
csv += "#{el[:name]},#{el[:id]},#{el[:sku][idx]},#{el[:qty][idx]}\n"
end
end
puts csv
结果:
#> bob,123,123a,2
#> bob,123,456b,4
#> bob,123,xyz1,1
#> kat,987,456b,8
#> kat,987,aaa0,9
#> kat,987,xyz1,5
#> kat,222,123a,4
我正在使用哈希数组创建一个 CSV 订单文件。 CSV 输出中的 name 和 id 需要在每一行都相同,但每个订单的行数取决于订单中的 skus 数量。
有没有简单的方法输出这个订单数组?
orders = []
orders << { name:"bob", id:123, sku:[ "123a", "456b", "xyz1" ], qty:[ 2, 4, 1 ] }
orders << { name:"kat", id:987, sku:[ "456b", "aaa0", "xyz1" ], qty:[ 8, 9, 5 ] }
orders << { name:"kat", id:222, sku:[ "123a" ], qty:[ 4 ] }
像这样的 CSV 文件:
name,id,sku,qty
bob,123,123a,2
bob,123,456b,4
bob,123,xyz1,1
kat,987,456b,8
kat,987,aaa0,9
kat,987,xyz1,5
kat,222,123a,4
首先,让我们准备要转储为 CSV 的数组:
asarray = orders.map { |e|
[e[:name], e[:id], e[:sku].zip(e[:qty])]
}.map { |e|
e.last.map { |sq| [*e[0..1], *sq] }
}
现在我们准备好将原始数组序列化为 CSV:
require 'csv'
CSV.open("path/to/file.csv", "wb") do |csv|
csv << ["name", "id", "sku", "qty"]
asarray.each { |order|
order.each { |row|
csv << row
}
}
end
试试这个:
module SKUSeparator
def map_by_skus
inject([]) do |csv, order|
order[:sku].each_with_index do |sku, index|
csv << [order[:name], order[:id], order[:sku][index], order[:qty][index]]
end
csv
end
end
def to_csv
map_by_skus.map { |line| line.join(",") }.join("\n")
end
end
ORDERS = [
{:name=>"bob", :id=>123, :sku=>["123a", "456b", "xyz1"], :qty=>[2, 4, 1]},
{:name=>"kat", :id=>987, :sku=>["456b", "aaa0", "xyz1"], :qty=>[8, 9, 5]},
{:name=>"kat", :id=>222, :sku=>["123a"], :qty=>[4]}
]
ORDERS.extend(SKUSeparator).map_by_skus # =>
# [
# ["bob", 123, "123a", 2],
# ["bob", 123, "456b", 4],
# ["bob", 123, "xyz1", 1],
# ["kat", 987, "456b", 8],
# ["kat", 987, "aaa0", 9],
# ["kat", 987, "xyz1", 5],
# ["kat", 222, "123a", 4]
# ]
ORDERS.extend(SKUSeparator).to_csv # =>
# bob,123,123a,2
# bob,123,456b,4
# bob,123,xyz1,1
# kat,987,456b,8
# kat,987,aaa0,9
# kat,987,xyz1,5
# kat,222,123a,4
作为变体:
orders = []
orders << { name:"bob", id:123, sku:[ "123a", "456b", "xyz1" ], qty:[ 2, 4, 1 ] }
orders << { name:"kat", id:987, sku:[ "456b", "aaa0", "xyz1" ], qty:[ 8, 9, 5 ] }
orders << { name:"kat", id:222, sku:[ "123a" ], qty:[ 4 ] }
csv = ''
orders.each do |el|
el[:qty].length.times do |idx|
csv += "#{el[:name]},#{el[:id]},#{el[:sku][idx]},#{el[:qty][idx]}\n"
end
end
puts csv
结果:
#> bob,123,123a,2
#> bob,123,456b,4
#> bob,123,xyz1,1
#> kat,987,456b,8
#> kat,987,aaa0,9
#> kat,987,xyz1,5
#> kat,222,123a,4