我有以下Ruby脚本:
arr = ['bob', 'jack', 'smith']
array_of_hashes = Array.new
hash = Hash.new
arr.each do |item|
hash.clear
hash[:name] = item
array_of_hashes << hash
end
puts array_of_hashes
返回一个哈希数组,其名称:名称键全部来自最后一个元素。
[
[0] {
:name => "smith"
},
[1] {
:name => "smith"
},
[2] {
:name => "smith"
}
]
我希望它能返回以下内容,但我一直试图弄清楚为什么最后一个Hash元素会覆盖所有以前的数组元素:
[
[0] {
:name => "bob"
},
[1] {
:name => "jack"
},
[2] {
:name => "smith"
}
]
编辑:谢谢大家的回答。很高兴有一些不同的方法来完成同样的事情。我测试了每个解决方案,每个解决方案都很棒。我最终使用的是与原始代码最相似的那个;但我的用例是一个简单的本地脚本 - 它不是在工业大小的应用程序中使用 - 在这种情况下,我可能会选择不同的解决方案。
答案 0 :(得分:5)
仔细查看您的代码,您会发现您只创建了Hash
的单个实例。你的迭代器继续用.clear
吹走早期的工作,将元素设置为当前迭代,并将对{1}}对象的引用添加到Hash
中的不同数组位置。但是在一天结束时,它们都指向同一个array_of_hashes
对象,而Hash
对象只包含你放入它的最后一个东西。
答案 1 :(得分:4)
注意(并理解)@pjs的答案和@tadman的评论,因为他们解释了为什么你会得到你得到的结果。
我实际上会做类似的事情:
const openni::SensorInfo* sinfo = device.getSensorInfo(openni::SENSOR_DEPTH);
const openni::Array< openni::VideoMode>& modesDepth = sinfo->getSupportedVideoModes();
depth.stop();
rc = depth.setVideoMode(modesDepth[4]);
depth.start();
一些注意事项:
names = ['bob', 'jack', 'smith']
# combine the results into an array of Hashes
array_of_hashes =
names.collect do |item|
{ name: item }
end
# output the results
array_of_hashes # [{name: "bob"}, {name: "jack"},{name:"smith"}]
方法会返回一个数组,因此您无需手动添加到已初始化自己的数组中。Array#collect
区块中返回的每个项目返回一个新的哈希答案 2 :(得分:3)
你应该尝试像
这样的东西arr = ['bob', 'jack', 'smith']
array_of_hashes = Array.new
arr.each { |item|
hash = Hash.new
hash[:name] = item
array_of_hashes << hash
}
puts array_of_hashes
将新实例推送到数组中以用于每个新项目。
答案 3 :(得分:2)
我会写
[:name].product(arr).map { |pair| Hash[[pair]] }
#=> [{:name=>"bob"}, {:name=>"jack"}, {:name=>"smith"}]
或(对于Ruby v2.0 +)
[:name].product(arr).map { |pair| [pair].to_h }
步骤:
a = [:name].product(arr)
#=> [[:name, "bob"], [:name, "jack"], [:name, "smith"]]
enum = a.map
# => #<Enumerator: [[:name, "bob"], [:name, "jack"], [:name, "smith"]]:map>
请注意,通过将方法Enumerator#each发送到enum
,我们可以获得所需的结果:
enum.each { |pair| [pair].to_h }
#=> [{:name=>"bob"}, {:name=>"jack"}, {:name=>"smith"}]
(Enumerator#each
会调用Array#each因为a.class #=> Array
。)
Enumerator#each
将块变量设置为enum
的第一个元素:
pair = enum.next
#=> [:name, "bob"]
并执行块计算:
[pair].to_h
#=> [[:name, "bob"]].to_h
#=> {:name=>"bob"}
接下来,enum
的第二个元素[:name, "jack"]
将映射到:
pair = enum.next
#=> [:name, "jack"]
[pair].to_h
#=> [[:name, "jack"]].to_h
#=> {:name=>"jack"}
最后,
pair = enum.next
#=> [:name, "smith"]
[pair].to_h
#=> [[:name, "smith"]].to_h
#=> {:name=>"smith"}
答案 4 :(得分:0)
你也可以尝试这个
>>> names = ['bob', 'jack', 'smith']
>>> names.inject([]){|s,p| s << {name: p}}
=> [{:name=>"bob"}, {:name=>"jack"}, {:name=>"smith"}]