我有一个如下所示的数组
unorganized_array = [
{:identifier => '1', :groupinfo => [{:color => 'blue', :texture => 'soft'}]},
{:identifier => '1', :groupinfo => [{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo => [{:color => 'red', :texture => 'spiky'}]}]
[{:identifier => ' 1',:groupinfo => [ {:color => ' blue',:texture => '软'}]}, {:identifier => ' 1',:groupinfo => [ {:color => ' green',:texture => '硬盘'}]}, {{:identifier => ' 2',:groupinfo => [{:color => ' red',:texture => '高低不平'}]}
我想将具有相同:identifier
的所有条目收集到该标识符:groupinfo
中。与前一个示例相比,这有一个额外的:identifier => '2'
组:
organized_array = [{:identifier => '1', :groupinfo => [
{:color => 'blue', :texture => 'soft'},
{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo =>
[{:color => 'red', :texture => 'spiky'},
{:color => 'gray', :texture => 'squishy}]}]
我觉得Hash#merge
和Hash#inject
在这里很有用,但我不确定如何实现它们。
我从一个看起来像
的数组中制作unorganized_arrayoriginal_array = [['blue', 'soft', '1', 'irrelevant'], ['green','hard','1','irrelevant1'],
['red','spiky','2','irrelevant2']]
也许有一种比从original_array更好的方法 - > unorganized_array - > organized_array?
到目前为止,我一直在尝试使用#map和#each for for循环将它们组合在一起,即
unorganized_array = original_array.map! do |first, second, third, fourth|
{:identifier => third, :groupinfo => [{:color => first, :texture => second}]}
end
答案 0 :(得分:1)
unorganized_array.map(&:dup)
.group_by { |e| e.delete(:identifier) }
.map { |k, v| [k, v.flat_map { |h| h[:groupinfo] } ] }
.map { |k, v| { identifier: k, groupinfo: v } }
上面给出了输入显示:
#⇒ [ { :groupinfo => [
# { :color => "blue", :texture => "soft" },
# { :color => "green", :texture => "hard" } ],
# :identifier => "1" },
# { :groupinfo => [
# { :color => "red", :texture => "spiky" } ],
# :identifier => "2" } ]
答案 1 :(得分:1)
目前,您正在生成一个2键哈希数组,其中第二个哈希包含一个属性数组。为什么不使用“标识符”作为key
的{{1}}?毕竟,这正是关键所在。
这看起来更干净:
Hash
这是产生这种情况的一种方式:
{"1"=>[{:color=>"blue", :texture=>"soft"},
{:color=>"green", :texture=>"hard"}],
"2"=>[{:color=>"red", :texture=>"spiky"}]}
至于Tin Man的观点,理解Ruby的my_hash = original_array.reduce({}) do |r,s|
r.merge( s[2] => (r[s[2]] || []) + [{color: s[0], texture: s[1]}] )
end
类是比发现我们可以提供的任何特定解决方案更有价值的目标。
这是迭代所有项目的一种方式。
Enumerable
输出:
my_hash.each do |key,arr|
puts "Identifier \##{key} has #{arr.size} items"
arr.each_with_index do |item,index|
puts "Item \##{index+1} is #{item[:color]} and #{item[:texture]}"
end
end
答案 2 :(得分:1)
arr =
[{:identifier => '1', :groupinfo => [{:color => 'blue, :texture => 'soft}]},
{:identifier => '1', :groupinfo => [{:color => 'green', :texture => 'hard'}]},
{:identifier => '2', :groupinfo => [{:color => 'red', :texture => 'spiky'}]}]
通过构建哈希,有几种方法可以做到这一点。
当散列h[k]
没有密钥h
时,使用Hash::new使用默认值来确定k
的格式。 < / p>
hash_with_default = Hash.new { |h,k| { identifier: k, groupdata: [] } }
arr.each_with_object(hash_with_default) { |g,h| h[g[:identifier]] =
{ identifier: g[:identifier],
groupdata: h[g[:identifier]][:groupdata] << g[:groupinfo].first } }.values
#=> [{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"},
# {:color=>"green", :texture=>"hard"}]},
# {:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]
使用Hash#update(又名merge!
)的形式使用块来确定合并的两个哈希中存在的键的值
arr.each_with_object({}) { |g,h| h.update(g[:identifier] => g) { |k,o,n|
{ identifier: o[:identifier], groupinfo: h[k][:groupinfo] + g[:groupinfo] } } }.values
#=> [{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"},
# {:color=>"green", :texture=>"hard"}]},
# {:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]
请参阅文档,了解三个区块变量k
,o
和n
的含义。
答案 3 :(得分:0)
我认为这不是最好的方法,但我建议这样做:
1-按标识符对数组进行分组
unorganized_array.group_by{|x| x[:identifier]}
#=> {"1"=>[{:identifier=>"1", :groupinfo=>[{:color=>"blue", :texture=>"soft"}]},
{:identifier=>"1", :groupinfo=>[{:color=>"green", :texture=>"hard"}]}],
"2"=>[{:identifier=>"2", :groupinfo=>[{:color=>"red", :texture=>"spiky"}]}]}
2 - 在预期的哈希中收集您的groups_array元素并收集组信息值。现在,数组中的每个元素都包含相关项。
group_array.each.collect {|k,g| { :identifier => k, :group_info => g.collect{ |x| x[:groupinfo].last } } }
3-结果是有组织的数组
[{:identifier=>"1", :group_info=>[
{:color=>"blue", :texture=>"soft"},
{:color=>"green", :texture=>"hard"}
]},
{:identifier=>"2", :group_info=>[{:color=>"red", :texture=>"spiky"}]}]