我有以下2个数组:
fields = ["name", "team", "number", "name", "team", "number", "name", "team", "number"]
values = ["Patrick Ewing", "New York Knicks", 33, "Rik Smits", "Indiana Pacers", 45, "Bill Russell", "Boston Celtics", 6]
字段将始终只是名称,团队和数字,但值的数量(即玩家数量)每次都会有所不同。
我想为每种字段类型创建新数组,以便我得到以下内容:
names = ["Patrick Ewing", "Rik Smits", "Bill Russell"]
teams = ["New York Knicks", "Indiana Pacers", "Boston Celtics"]
numbers = [33,45,6]
这样做的好方法是什么?我尝试了以下内容,但想知道是否有其他解决方案可以更好地使用更大的阵列(最多300个)。或者差异可以忽略不计?
names = values.values_at(*(fields.each_index.select{ |i| fields[i] == "name"}))
teams = values.values_at(*(fields.each_index.select{ |i| fields[i] == "team"}))
numbers = values.values_at(*(fields.each_index.select{ |i| fields[i] == "number"}))
答案 0 :(得分:5)
这是另一种/简洁的方式:
> name, team, number = values.each_slice(3).to_a.transpose
=> name
> ["Patrick Ewing", "Rik Smits", "Bill Russell"]
=> team
> ["New York Knicks", "Indiana Pacers", "Boston Celtics"]
=> number
> [33, 45, 6]
Ruby Array#transpose的美丽发挥作用,尤其适用于您的问题。
答案 1 :(得分:3)
您可以在一行中使用group_by
和with_index
:
grouped = values.group_by.with_index {|_, i| fields[i] }
#=> {"name"=>["Patrick Ewing", "Rik Smits", "Bill Russell"],'
"team"=>["New York Knicks", "Indiana Pacers", "Boston Celtics"],
"number"=>[33, 45, 6]}
然后,您可以从此哈希中简单地生成数组:
name = grouped["name"]
#=> ["Patrick Ewing", "Rik Smits", "Bill Russell"]
或者只是:
names, teams, numbers = grouped.values
答案 2 :(得分:2)
如果输入始终为三个一组,则可以使用each_slice
:
values = ["Patrick Ewing", "New York Knicks", 33, "Rik Smits", "Indiana Pacers", 45, "Bill Russell", "Boston Celtics", 6]
names = [ ]
teams = [ ]
numbers = [ ]
values.each_slice(3) do |name, team, number|
names << name
teams << team
numbers << number
end
这不是组织事物的最佳方式。更加面向Ruby的风格是:
keys = [ :name, :team, :number ]
players = values.each_slice(3).collect do |set|
Hash[keys.zip(set)]
end
#=> [{:name=>"Patrick Ewing", :team=>"New York Knicks", :number=>33}, {:name=>"Rik Smits", :team=>"Indiana Pacers", :number=>45}, {:name=>"Bill Russell", :team=>"Boston Celtics", :number=>6}]
这使您可以轻松访问每条记录,而无需交叉引用多个数组。即使您在表格中显示此内容并且需要单独使用这三项内容,您仍然可以选择输出单个值:
keys.each do |key|
players.each do |player|
print '%-20s' % player[key]
end
puts
end
这会给你输出:
Patrick Ewing Rik Smits Bill Russell
New York Knicks Indiana Pacers Boston Celtics
33 45 6
答案 3 :(得分:1)
以下是通过“type”对数组值进行分组的一种方法:
fields = ["name", "team", "number", "name", "team", "number", "name", "team", "number"]
values = ["Patrick Ewing", "New York Knicks", 33, "Rik Smits", "Indiana Pacers", 45, "Bill Russell", "Boston Celtics", 6]
field_values = fields.zip(values)
names = field_values.select { |f, v| f == "name" }.map(&:last)
# => ["Patrick Ewing", "Rik Smits", "Bill Russell"]
teams = field_values.select { |f, v| f == "team" }.map(&:last)
# => ["New York Knicks", "Indiana Pacers", "Boston Celtics"]
numbers = field_values.select { |f, v| f == "number" }.map(&:last)
# => [33, 45, 6]
答案 4 :(得分:1)
另一种方式:使用Facets Enumerable#map_by:
require 'facets'
names, teams, numbers = fields.zip(values).
map_by { |field, value| [field, value] }.
values_at("name", "team", "number")