Ruby - 在键入哈希之前删除项目

时间:2016-02-10 19:06:11

标签: ruby

在定义键之前可以删除散列中的项目吗?例如:

hash = {
  :foo => {"name" => "foo"},
  :bar => {"name" => "bar"},
  :baz => {"name" => "baz"}
}
# ToDo: remove items before :bar
result = {
  :bar => {"name" => "bar"},
  :baz => {"name" => "baz"}
}

我该怎么做?

3 个答案:

答案 0 :(得分:4)

Ruby Hashes实际上并不是被设计为被视为有序集合,因此这并不像您期望的那样简单。但它们确实维护了关键的插入顺序,至少从Ruby 1.9开始,所以它是可能的。

这是一种方式;可能有更好的:

hash.delete(*hash.keys.each_with_index.find do |k, n| 
  n < hash.keys.each_with_index.select{|k,n| k==:bar}[1]
end.map(&:first))

首先,我们向哈希询问带有.keys的密钥,它返回一个数组。然后我们在该数组上调用each_with_index以将每个项目与数字索引相关联,所以现在我们迭代对(键,索引)。我们使用.find搜索我们想要的密钥(k == :bar),并使用[1]获取其索引编号。

然后我们重新开始并使用.select搜索相同的(密钥,索引)对列表,以查找索引 less 的所有密钥,而不是:bar的索引。这次我们想要键而不是索引,所以我们通过.first ping它们对每个对上调用map

使用我们想要删除的键数组;我们使用*运算符将它们转换为参数列表,并将它们传递给Hash上的.delete以实际删除它们。

答案 1 :(得分:3)

以下是一种方法:

hash.to_a.drop_while { |k, _| k != :bar }.to_h

正如马克指出的那样,旧版本的Ruby

Hash[*hash.to_a.drop_while { |k, _| k != :bar }]

答案 2 :(得分:1)

您可以使用Ruby使用不多的flip-flop operator

hash = {
  :foo => {"name" => "foo"},
  :bar => {"name" => "bar"},
  :baz => {"name" => "baz"},
  :qux => {"name" => "qux"}
}

key = :baz

hash.select { |k,_| k==key..nil ? true : false }
  #=> {:baz=>{"name"=>"baz"}, :qux=>{"name"=>"qux"}} 

第二种方式如下。

ndx = hash.keys.index(key)
  #=> 2
arr = [*[false]*ndx, *[true]*(hash.size-ndx)]
  #=> [false, false, true, true] 
hash.select { arr.shift }
  #=> {:baz=>{"name"=>"baz"}, :qux=>{"name"=>"qux"}}