如何从哈希返回除第一个键/值对之外的所有元素

  • 本文关键字:元素 哈希 返回 第一个 ruby
  • 更新时间 :
  • 英文 :


我想返回哈希中的所有元素,不包括第一个键/值对。

我的经验有限,所以我使用的.except,因为它是非破坏性的。

h = {a: 1, b: 2, c: 3}
# I want to return
h = {b: 2, c: 3}
# using this code
h.exclude(:a)
# or something similar

请注意,Hash的"first"这个想法有点可疑。的确,Ruby 中的Hashes 是按插入顺序排列的,这是由规范保证的,因此您可以在每个平台上的每个实现中依赖它,但一般来说Hash的目的是按键查找值,而不是依赖顺序。

例如,无法保证:a将是示例中的第一个键。这完全取决于Hash的创建方式以及添加键的顺序。

话虽如此,有一种Enumerable方法可以完全按照您的要求执行:删除Enumerable的前n个元素,毫不奇怪地将其命名为Enumerable#drop

请注意,由于它是一种Enumerable方法,因此它对Hashes 一无所知,它所知道的唯一方法是#each。因此,它将返回任何#each产生的Array,在Hash的情况下,这是一个双元素[key, value]对:

h.drop(1)
#=> [[:b, 2], [:c, 3]]

幸运的是,有一种方法可以将双元素Arrays的Enumerable转换为Hash,即Enumerable#to_h

h.drop(1).to_h
#=> { b: 2, c: 3 }

h.except(:a)可以使用rails/activesupport,但它需要你知道密钥的名称。

寻址第一个元素更棘手,因为哈希作为一种数据结构,没有键值对的顺序。但好消息是,在 ruby(或至少是 MRI/YARV)中,哈希确实保持了插入顺序,并且在迭代键值对时会反映出来。所以你可以做这样的事情:

pairs = h.to_a # get all KV pairs as an array
except_first = pairs[1..-1] # discard the first KV pair
except_first.to_h # make a hash

或者,更简洁地说

h.drop(1).to_h

您可以将#shift#tap一起使用,如下所示:

h = {a: 1, b: 2, c: 3}
h.tap(&:shift) # => {:b=>2, :c=>3}

我不喜欢将哈希转换为数组,操作数组,然后将修改后的数组转换回哈希的想法,所以我使用了 Hash#reject。

h = {a: 1, b: 2, c: 3}

h.reject { |k,_| k == h.first.first }
#=> {:b=>2, :c=>3} 

h.reject.with_index { |_,i| i.zero? }
#=> {:b=>2, :c=>3} 

x = 1
h.reject { (x -= 1).zero? }
#=> {:b=>2, :c=>3}

最新更新