我正在尝试为数组中的每个哈希获取一个键的子集。
哈希实际上要大得多,但我认为这更容易理解:
[
{
id:2,
start: "3:30",
break: 30,
num_attendees: 14
},
{
id: 3,
start: "3: 40",
break: 40,
num_attendees: 4
},
{
id: 4,
start: "4: 40",
break: 10,
num_attendees: 40
}
]
我想只获取id
和start
值。
我试过了:
return_keys = ['id','start']
return_array = events.select{|key,val| key.to_s.in? return_keys}
但这会返回一个空数组。
答案 0 :(得分:44)
这应该做你想要的:
events.map do |hash|
hash.select do |key, value|
[:id, :start].include? key
end
end
可能更快(但不那么漂亮)的解决方案:
events.map do |hash|
{ id: hash[:id], start: hash[:start] }
end
如果您需要动态return_keys
:
return_keys = [:id, :start]
events.map do |hash|
{}.tap do |new_hash|
return_keys.each do |key|
new_hash[key] = hash[key]
end
end
end
请注意,在您的代码中,select
会从数组中选择元素,因为这是您调用它的内容,但不会更改数组中包含的哈希值。< / p>
如果您对性能感到担忧,我会对此处列出的所有解决方案进行基准测试(code):
user system total real
amarshall 1 0.140000 0.000000 0.140000 ( 0.140316)
amarshall 2 0.060000 0.000000 0.060000 ( 0.066409)
amarshall 3 0.100000 0.000000 0.100000 ( 0.101469)
tadman 1 0.140000 0.010000 0.150000 ( 0.145489)
tadman 2 0.110000 0.000000 0.110000 ( 0.111838)
mu 0.130000 0.000000 0.130000 ( 0.128688)
答案 1 :(得分:32)
如果你碰巧使用Rails(或者不介意拉入全部或部分ActiveSupport),那么你可以使用Hash#slice
:
return_array = events.map { |h| h.slice(:id, :start) }
Hash#slice
做了一些额外的工作,但它可能足够快,你不会注意到它的小哈希和清晰度是相当不错的。
答案 2 :(得分:2)
更好的解决方案是使用散列作为索引,而不是为每个键执行线性数组查找:
events = [{id:2, start:"3:30",break:30,num_attendees:14},{id:3, start:"3:40",break:40,num_attendees:4},{id:4, start:"4:40",break:10,num_attendees:40}]
return_keys = [ :id, :start ]
# Compute a quick hash to extract the right values: { key => true }
key_index = Hash[return_keys.collect { |key| [ key, true ] }]
return_array = events.collect do |event|
event.select do |key, value|
key_index[key]
end
end
# => [{:id=>2, :start=>"3:30"}, {:id=>3, :start=>"3:40"}, {:id=>4, :start=>"4:40"}]
我已将此调整为使用符号作为键名,以匹配您对events
的定义。
使用return_keys
作为直接驱动程序可以进一步改善这一点:
events = [{id:2, start:"3:30",break:30,num_attendees:14},{id:3, start:"3:40",break:40,num_attendees:4},{id:4, start:"4:40",break:10,num_attendees:40}]
return_keys = [ :id, :start ]
return_array = events.collect do |event|
Hash[
return_keys.collect do |key|
[ key, event[key] ]
end
]
end
结果是一样的。如果您提取的子集往往比原始子集小得多,这可能是最好的方法。
答案 3 :(得分:0)
考虑到效率似乎是一个问题,我建议如下。
<强>代码强>
require 'set'
def keep_keys(arr, keeper_keys)
keepers = keeper_keys.to_set
arr.map { |h| h.select { |k,_| keepers.include?(k) } }
end
这使用Hash#select,与Enumerable#select不同,它返回一个哈希值。我已将keeper_keys
转换为快速查找的集合。
<强>实施例强>
arr = [{ id:2, start: "3:30", break: 30 },
{ id: 3, break: 40, num_attendees: 4 },
{ break: 10, num_attendees: 40 }]
keep_keys arr, [:id, :start]
#=> [{:id=>2, :start=>"3:30"}, {:id=>3}, {}]
keep_keys arr, [:start, :break]
#=> [{:start=>"3:30", :break=>30}, {:break=>40}, {:break=>10}]
keep_keys arr, [:id, :start, :cat]
#=> [{:id=>2, :start=>"3:30"}, {:id=>3}, {}]
keep_keys arr, [:start]
#=> [{:start=>"3:30"}, {}, {}]
keep_keys arr, [:cat, :dog]