Arrays 如何在Ruby中将数组转换为另一个数组
我有这样一个多维数组:Arrays 如何在Ruby中将数组转换为另一个数组,arrays,ruby,csv,Arrays,Ruby,Csv,我有这样一个多维数组: myArray = [["Alaska","Rain","3"],["Alaska","Snow","4"],["Alabama","Snow","2"],["Alabama","Hail","1"]] 我想以这样的CSV输出结束 State,Snow,Rain,Hail Alaska,4,3,nil Alabama,2,nil,1 我知道要以我想要的方式将其输出到CSV,我必须有如下输出数组: outputArray =[["State","Snow","Rain"
myArray = [["Alaska","Rain","3"],["Alaska","Snow","4"],["Alabama","Snow","2"],["Alabama","Hail","1"]]
我想以这样的CSV输出结束
State,Snow,Rain,Hail
Alaska,4,3,nil
Alabama,2,nil,1
我知道要以我想要的方式将其输出到CSV,我必须有如下输出数组:
outputArray =[["State","Snow","Rain","Hail"],["Alaska",4,3,nil],["Alabama",2,nil,1]]
但我不知道如何进入这个阶段。
我尝试过使用group_by,但没有成功。我认为您可能需要为此行为创建一个自定义的
类,以便将整个功能包装到一个对象中
该类将接受输入数组的一个实例,并将返回已转换的输出,以便进行序列化
您需要的是:
包含标头列表的数组,在循环输入项时动态填充
一种散列,其中键是状态,值是头/值的散列
{ "Alabama" => { "Snow" => 2 }}
初始化对象时,@headers
是空数组,@data
是空哈希
您循环输入数组中的所有项目,对于列表中的每个项目,如果尚未添加到@headers
(事实上,您可以使用集合
,而不是数组
,它将为您删除重复项),然后将项目添加到@数据
如果国家/地区中已存在该状态,请添加新的键/值。如果状态不存在,则创建状态并添加新的键/值。您可以通过一行代码轻松实现此目标
# assuming `state` is the current state in the loop
(@data[state] ||= {}).merge(header => value)
循环结束时,@header
将包含要显示的所有项目。此时,循环@data
并为每个项目提取@header
中声明的所有值。如果该值不存在,请使用nil
在第二个循环结束时,您将获得生成CSV所需的数据。我认为您可能需要为此行为创建一个自定义的类
,以便将整个功能包装到一个对象中
该类将接受输入数组的一个实例,并将返回已转换的输出,以便进行序列化
您需要的是:
包含标头列表的数组,在循环输入项时动态填充
一种散列,其中键是状态,值是头/值的散列
{ "Alabama" => { "Snow" => 2 }}
初始化对象时,@headers
是空数组,@data
是空哈希
您循环输入数组中的所有项目,对于列表中的每个项目,如果尚未添加到@headers
(事实上,您可以使用集合
,而不是数组
,它将为您删除重复项),然后将项目添加到@数据
如果国家/地区中已存在该状态,请添加新的键/值。如果状态不存在,则创建状态并添加新的键/值。您可以通过一行代码轻松实现此目标
# assuming `state` is the current state in the loop
(@data[state] ||= {}).merge(header => value)
循环结束时,@header
将包含要显示的所有项目。此时,循环@data
,并为每个项目提取@header
中声明的所有值。如果该值不存在,请使用nil
在第二个循环结束时,您将获得生成CSV所需的数据。这里有一种使用散列的中间散列的方法
h
最后看起来像这样
{"Alaska"=>{"Rain"=>"3", "Snow"=>"4"}, "Alabama"=>{"Snow"=>"2", "Hail"=>"1"}}
输出
[["State", "Snow", "Rain", "Hail"], ["Alaska", "4", "3", nil], ["Alabama", "2", nil, "1"]]
下面是一种使用散列的中间散列的方法
h
最后看起来像这样
{"Alaska"=>{"Rain"=>"3", "Snow"=>"4"}, "Alabama"=>{"Snow"=>"2", "Hail"=>"1"}}
输出
[["State", "Snow", "Rain", "Hail"], ["Alaska", "4", "3", nil], ["Alabama", "2", nil, "1"]]
我建议你按如下方式做:
my_array = [["Alaska" ,"Rain","3"], ["Alaska", "Snow","4"],
["Alabama","Snow","2"], ["Alabama","Hail","1"]]
attributes = my_array.transpose[1].uniq
#=> ["Rain", "Snow", "Hail"]
h = my_array.each_with_object({}) { |a,h| (h[a.first] ||= {})[a[1]] = a[2].to_i }
#=> {"Alaska" =>{"Rain"=>3, "Snow"=>4},
# "Alabama"=>{"Snow"=>2, "Hail"=>1}}
[["State", *attributes], *h.map { |k,v| [k, *v.values_at(*attributes)] }]
#=> [["State", "Rain", "Snow", "Hail"],
# ["Alaska", 3, 4, nil],
# ["Alabama", nil, 2, 1]]
当然,您可以替换掉h
让我们更仔细地看一下以下各项的计算:
h.map { |k,v| [k, *v.values_at(*attributes)] }]
我们有:
enum = h.map
#=> #<Enumerator: {"Alaska"=>{"Rain"=>3, "Snow"=>4},
# "Alabama"=>{"Snow"=>2, "Hail"=>1}}:map>
enum
的第二个元素被传递到块中:
k,v = enum.next
#=> ["Alabama", {"Snow"=>2, "Hail"=>1}]
b = v.values_at(*attributes)
#=> [nil, 2, 1]
[k, *b]
#=> ["Alabama", nil, 2, 1]
我建议你按如下方式做:
my_array = [["Alaska" ,"Rain","3"], ["Alaska", "Snow","4"],
["Alabama","Snow","2"], ["Alabama","Hail","1"]]
attributes = my_array.transpose[1].uniq
#=> ["Rain", "Snow", "Hail"]
h = my_array.each_with_object({}) { |a,h| (h[a.first] ||= {})[a[1]] = a[2].to_i }
#=> {"Alaska" =>{"Rain"=>3, "Snow"=>4},
# "Alabama"=>{"Snow"=>2, "Hail"=>1}}
[["State", *attributes], *h.map { |k,v| [k, *v.values_at(*attributes)] }]
#=> [["State", "Rain", "Snow", "Hail"],
# ["Alaska", 3, 4, nil],
# ["Alabama", nil, 2, 1]]
当然,您可以替换掉h
让我们更仔细地看一下以下各项的计算:
h.map { |k,v| [k, *v.values_at(*attributes)] }]
我们有:
enum = h.map
#=> #<Enumerator: {"Alaska"=>{"Rain"=>3, "Snow"=>4},
# "Alabama"=>{"Snow"=>2, "Hail"=>1}}:map>
enum
的第二个元素被传递到块中:
k,v = enum.next
#=> ["Alabama", {"Snow"=>2, "Hail"=>1}]
b = v.values_at(*attributes)
#=> [nil, 2, 1]
[k, *b]
#=> ["Alabama", nil, 2, 1]
此问题需要更多@sawa。此问题需要更多@sawa。详细信息:OP希望将表示整数的字符串转换为整数。@CarySwoveland,当写入CSV文件时没有任何区别h[i][j]=k.to_i
可以在需要时执行。详细信息:OP希望表示整数的字符串转换为整数。@CarySwoveland,在写入CSV文件时没有任何区别h[i][j]=k.to\u如果需要的话我会做的。我用你的v.values\u在(*属性)
来改进我的答案:)我用你的v.values\u在(*属性)
来改进我的答案:)