计算哈希值的排名并将其插入 Ruby 中的 CSV 文件
Calculate rank of hash value and insert it into a CSV file in Ruby
我有一个散列
h1 = {"Cust1"=>500, "Cust4"=>400, "Cust2"=>100, "Cust3"=>100}
我想将这个散列插入到一个 CSV 文件中,其中包含根据键值排序的键。
示例输出应如下所示
ID,Sales,Rank Cust1,500,1 Cust4,400,2 Cust2,100,3 Cust3,100,3
我得把程序写在Ruby.
可以使用each_with_index
散列的方法
arr = [['ID', 'Sales', 'Rank']]
h1.each_with_index do |(key, value), index|
arr << [key, value, index + 1]
end
arr #[["ID", "Sales", "Rank"], ["Cust1", 500, 1], ["Cust4", 400, 2], ["Cust2", 100, 3], ["Cust3", 100, 4]]
CSV 代码
h1 = {"Cust1"=>500, "Cust4"=>400, "Cust2"=>100, "Cust3"=>100}
# You can skip following `sort_by` line if your hash is already ordered by desc value
h1 = h1.sort_by {|_k,v| v}.reverse.to_h
h2 = h1.group_by {|k,v| v }
require 'csv'
CSV.open("myfile.csv", "w") do |csv|
csv << ['ID', 'Sales', 'Rank']
h2.each_with_index do |(key, values), index|
values.each do |value|
csv << [value[0], key, index + 1]
end
end
end
OP要求计算排名;因为 1.9 Ruby 保留了哈希的插入顺序,在这种情况下,哈希 h1
已经处于正确的顺序。但是,如果数据来自 REST 调用或尚未按排名顺序排序,则上述解决方案将产生不正确的输出。解决这个问题
require 'csv'
h1 = {"Cust1"=>500, "Cust2"=>100, "Cust4"=>400, "Cust3"=>100}
ranked_customers = h1.sort_by { |k, v| [-v, k] }.each_with_index { |e, i| e.push i + 1 }
ranked_customers.unshift %w[ID Sales Rank]
CSV { |csv_out| ranked_customers.each { |e| csv_out << e } }
生产
ID,Sales,Rank
Cust1,500,1
Cust4,400,2
Cust2,100,3
Cust3,100,4
Cust2 和 Cust3 的销售额相同,但 Cust2 按字母顺序排在 Cust3 之前。
我假设 key-value 对 h1
不一定按值递减的顺序排列。
我们需要进行两次计算来构建 CSV 文件。
order = h1.sort_by { |_,v| -v }
#=> [["Cust1", 500], ["Cust4", 400], ["Cust2", 100], ["Cust3", 100]]
nbr_ranks = order.map(&:last).uniq.size
#=> 3
文件可以按如下方式构造。
require 'csv'
CSV.open('t.csv', 'w') do |csv|
csv << ['ID', 'Sales', 'Rank']
last_val = order.first.last
order.each do |name, val|
unless val == last_val
nbr_ranks -= 1
last_val = val
end
csv << [name, val, nbr_ranks]
end
end
puts File.read('t.csv')
ID,Sales,Rank
Cust1,500,1
Cust4,400,2
Cust2,100,3
Cust3,100,4
如果 h1
的 key-value 对保证按值递减的顺序排列(如示例所示),则无需计算数组 order
。
nbr_ranks = order.map(&:last).uniq.size
#=> 3
CSV.open('t.csv', 'w') do |csv|
csv << ['ID', 'Sales', 'Rank']
last_val = h1[h1.keys.first]
h1.each do |name, val|
unless val == last_val
nbr_ranks -= 1
last_val = val
end
csv << [name, val, nbr_ranks]
end
end
注:
last_val = h1[h1.keys.first]
#=> 500
我有一个散列
h1 = {"Cust1"=>500, "Cust4"=>400, "Cust2"=>100, "Cust3"=>100}
我想将这个散列插入到一个 CSV 文件中,其中包含根据键值排序的键。
示例输出应如下所示
ID,Sales,Rank Cust1,500,1 Cust4,400,2 Cust2,100,3 Cust3,100,3
我得把程序写在Ruby.
可以使用each_with_index
散列的方法
arr = [['ID', 'Sales', 'Rank']]
h1.each_with_index do |(key, value), index|
arr << [key, value, index + 1]
end
arr #[["ID", "Sales", "Rank"], ["Cust1", 500, 1], ["Cust4", 400, 2], ["Cust2", 100, 3], ["Cust3", 100, 4]]
CSV 代码
h1 = {"Cust1"=>500, "Cust4"=>400, "Cust2"=>100, "Cust3"=>100}
# You can skip following `sort_by` line if your hash is already ordered by desc value
h1 = h1.sort_by {|_k,v| v}.reverse.to_h
h2 = h1.group_by {|k,v| v }
require 'csv'
CSV.open("myfile.csv", "w") do |csv|
csv << ['ID', 'Sales', 'Rank']
h2.each_with_index do |(key, values), index|
values.each do |value|
csv << [value[0], key, index + 1]
end
end
end
OP要求计算排名;因为 1.9 Ruby 保留了哈希的插入顺序,在这种情况下,哈希 h1
已经处于正确的顺序。但是,如果数据来自 REST 调用或尚未按排名顺序排序,则上述解决方案将产生不正确的输出。解决这个问题
require 'csv'
h1 = {"Cust1"=>500, "Cust2"=>100, "Cust4"=>400, "Cust3"=>100}
ranked_customers = h1.sort_by { |k, v| [-v, k] }.each_with_index { |e, i| e.push i + 1 }
ranked_customers.unshift %w[ID Sales Rank]
CSV { |csv_out| ranked_customers.each { |e| csv_out << e } }
生产
ID,Sales,Rank
Cust1,500,1
Cust4,400,2
Cust2,100,3
Cust3,100,4
Cust2 和 Cust3 的销售额相同,但 Cust2 按字母顺序排在 Cust3 之前。
我假设 key-value 对 h1
不一定按值递减的顺序排列。
我们需要进行两次计算来构建 CSV 文件。
order = h1.sort_by { |_,v| -v }
#=> [["Cust1", 500], ["Cust4", 400], ["Cust2", 100], ["Cust3", 100]]
nbr_ranks = order.map(&:last).uniq.size
#=> 3
文件可以按如下方式构造。
require 'csv'
CSV.open('t.csv', 'w') do |csv|
csv << ['ID', 'Sales', 'Rank']
last_val = order.first.last
order.each do |name, val|
unless val == last_val
nbr_ranks -= 1
last_val = val
end
csv << [name, val, nbr_ranks]
end
end
puts File.read('t.csv')
ID,Sales,Rank
Cust1,500,1
Cust4,400,2
Cust2,100,3
Cust3,100,4
如果 h1
的 key-value 对保证按值递减的顺序排列(如示例所示),则无需计算数组 order
。
nbr_ranks = order.map(&:last).uniq.size
#=> 3
CSV.open('t.csv', 'w') do |csv|
csv << ['ID', 'Sales', 'Rank']
last_val = h1[h1.keys.first]
h1.each do |name, val|
unless val == last_val
nbr_ranks -= 1
last_val = val
end
csv << [name, val, nbr_ranks]
end
end
注:
last_val = h1[h1.keys.first]
#=> 500