我试图在Ruby中编写一个程序,允许一个数组从另一个数组接收信息。基本上,我有一个名为" student_array"的多维数组。其中包含少数学生的信息
student_array = [["Mike", 13, "American", "male"],
["Grace", 12, "Canadian", "female"],
["Joey", 13, "American", "male"],
["Lily", 13, "American", "female"]
]
我还初始化了另外两个将统计国籍的阵列:
nationality_array = Array.new
nationality_count = Array.new
该计划的目的是循环学生数组,计算学生的不同国籍,并创建一个CSV文件,其中包含不同国籍的标题,以及每个国家的计数。
预期output.csv
American, Canadian
3, 1
这是我到目前为止的代码
student_array.each do |student|
#pushes the nationality string into the nationality array
nationality_array.push(student[2])
end
所以nationality_array目前应该是这样的:
nationality_array = ["American", "Canadian", "American", "American"];
nationality_array.uniq = ["American", "Canadian"];
所以我会有两个标题 - " American"和#34;加拿大"
现在我需要一种方法来遍历student_array,计算" American"的每个实例。和"加拿大",并以某种方式将其分配回国籍阵列。我很难想象如何解决这个问题。这是我到目前为止 -
american_count = 0;
canadian_count = 0;
student_array.each do |student|
if student[2] = "American"
american_count++
elsif student[2] = "Canadian"
canadian_count++
end
end
nationality_count.push(american_count);
nationality_count.push(canadian_count);
好的,现在我在nationality_count数组中有这些计数,但是如何将它传递给CSV,确保它们被分配到正确的标题?我觉得我的代码非常笨拙,而且可以更精简。
它可能看起来像这样?
CSV.open("output/redemptions.csv", "wb") do |csv|
csv << [nationality_array]
csv << [nationality_count]
end
任何人都可以提供更清晰的方法吗?
答案 0 :(得分:3)
Array#group_by和ActiveSupport中的Hash#transform_values是两种非常有用的方法,可以在这里使用:
require 'active_support/all'
require 'csv'
student_array = [
["Mike", 13, "American", "male"],
["Grace", 12, "Canadian", "female"],
["Joey", 13, "American", "male"],
["Lily", 13, "American", "female"]
]
counts = student_array.group_by { |attrs| attrs[2] }.transform_values(&:length)
# => => {"American"=>3, "Canadian"=>1}
CSV.open("output/redemptions.csv", "wb") do |csv|
csv << counts.keys
csv << counts.values
end
puts File.read "output/redemptions.csv"
# => American,Canadian
# 3,1
.group_by { |attrs| attrs[2] }
将数组转换为哈希值,其中键是attrs[2]
的唯一值,值是具有attrs[2]
的元素列表。此时,您可以使用transform_values
将这些值转换为表示其长度的数字(表示具有该特定attrs[2]
的元素数量)。然后可以从散列中提取键和值作为单独的数组。
答案 1 :(得分:3)
您可以使用Hash
按国籍而不是不同的数组对计数进行分组。
nationalities_count = student_array.each_with_object(Hash.new(0)) do |student, hash|
nationality = student[2]
hash[nationality] += 1
end
这会给你一个看起来像
的哈希{ "American" => 2, "Canadian" => 1 }
然后您可以使用Hash#to_a
和Array#transpose
,如下所示:
hsh = { "American" => 2, "Canadian" => 1 }
=> {"American"=>2, "Canadian"=>1}
2.4.2 :002 > hsh.to_a
=> [["American", 2], ["Canadian", 1]]
2.4.2 :003 > hsh.to_a.transpose
=> [["American", "Canadian"], [2, 1]]
最后,要输出CSV文件,您只需将数组写入文件
即可nationalities_with_count = hash.to_a.transpose
CSV.open("output/redemptions.csv", "wb") do |csv|
csv << nationalities_with_count[0]
csv << nationalities_with_count[1]
end
答案 2 :(得分:2)
您甚至不需要CSV工具:
result =
student_array.
map { |a| a[2] }. # get nationalities
group_by { |e| e }. # hash
map { |n, c| [n, c.count] }. # map values to count
transpose. # put data in rows
map { |row| row.join ',' }. # join values in a row
join($/) # join rows
#⇒ American,Canadian
# 3,1
现在你有一个有效的CSV字符串,只需将其吐出到文件中。