我想返回哈希中的所有元素,不包括第一个键/值对。
我的经验有限,所以我使用的.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 中的Hash
es 是按插入顺序排列的,这是由规范保证的,因此您可以在每个平台上的每个实现中依赖它,但一般来说,Hash
的目的是按键查找值,而不是依赖顺序。
例如,无法保证:a
将是示例中的第一个键。这完全取决于Hash
的创建方式以及添加键的顺序。
话虽如此,有一种Enumerable
方法可以完全按照您的要求执行:删除Enumerable
的前n
个元素,毫不奇怪地将其命名为Enumerable#drop
。
请注意,由于它是一种Enumerable
方法,因此它对Hash
es 一无所知,它所知道的唯一方法是#each
。因此,它将返回任何#each
产生的Array
,在Hash
的情况下,这是一个双元素[key, value]
对:
h.drop(1)
#=> [[:b, 2], [:c, 3]]
幸运的是,有一种方法可以将双元素Array
s的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}