Accessing the last key–value pair in a Ruby (1.9) hash

25,083

Solution 1

Nothing built in, no. But you could monkey-patch one if you were so inclined (not usually recommended, of course):

class Hash
  def last_value
    values.last
  end
end

And then:

hash.last_value

Solution 2

Hash have a "first" method, but that return the first pair in array mode, for last, you can try:

my_hash.to_a.last

this return last pair in array mode like "first method"

Solution 3

One more alternative that I'm using myself:

hash[hash.keys.last]

which works out better when you want to directly assign a value onto the last element of the hash:

2.4.1 :001 > hash = {foo: 'bar'}
 => {:foo=>"bar"} 
2.4.1 :002 > hash[hash.keys.last] = 'baz'
 => "baz" 
2.4.1 :003 > hash.values.last = 'bar'
NoMethodError: undefined method `last=' for ["baz"]:Array
Did you mean?  last
    from (irb):3
    from /home/schuylr/.rvm/rubies/ruby-2.4.1/bin/irb:11:in `<main>'

Solution 4

I just did this for a very large hash:

hash.reverse_each.with_index do |(_, value), index|
  break value if (index == 0)
end
Share:
25,083

Related videos on Youtube

davidchambers
Author by

davidchambers

Updated on August 03, 2020

Comments

  • davidchambers
    davidchambers almost 4 years

    As of Ruby 1.9, hashes retain insertion order which is very cool. I want to know the best way to access the last key–value pair.

    I've written some code which does this:

    hash.values.last
    

    This works and is very easy to comprehend, but perhaps it's possible to access the last value directly, rather that via an intermediary (the array of values). Is it?

  • Constant Meiring
    Constant Meiring almost 9 years
    This is an awesome solution!
  • Janosch
    Janosch about 6 years
    This is about 2-3 times faster: v = hash.each_value.reverse_each.next rescue StopIteration. Still 2-3 times slower than hash.values.last for 100M entries, though.
  • Janosch
    Janosch about 6 years
    Looking up why this is so slow, I found that #reverse_each only makes sense on Arrays. Hash and other Enumerables first create an intermediate Array when #reverse_each is called, in the case of Hash one with all keys and values.
  • Edgar Ortega
    Edgar Ortega almost 6 years
    In new Ruby versions you could also do hash.values.last
  • sjagr
    sjagr almost 6 years
    @EdgarOrtega that's exactly what davidchambers was using and led them to asking this question.
  • Edgar Ortega
    Edgar Ortega almost 6 years
    @sjagr 😅, I was pointing to this specific question, but yeah, you're right!
  • sjagr
    sjagr almost 6 years
    @EdgarOrtega the power of my answer is that you can easily do this hash[hash.keys.last] = 'bar' whereas you cannot do this hash.values.last = 'bar'