8

I am looking at http://ruby-doc.org/core-1.9.3/Hash.html and there does not appear to be a pop method? I think I am missing something though...

if (x = d['a']) != nil
  d.delete('a') 
end
user3467349
  • 3,043
  • 4
  • 34
  • 61
  • What is your question? – Cary Swoveland May 15 '15 at 02:45
  • Is there really no better way to `pop` an item from a Hash? Is there a reason I shouldn't worry about it? (I'm not familiar with how Ruby is compiled, so I don't know if the lack of a singular method is a big deal like it would be in Python). – user3467349 May 15 '15 at 02:46
  • 1
    You are referring to a `pop()` method which conventionally implies removing (and returning) the last element from a collection. You example code doesn't appear to be doing that though. What action specifically do you want to take? – Michael Berkowski May 15 '15 at 02:51
  • @MichaelBerkowski My code does exactly what `pop` does. You are welcome to try it. – user3467349 May 15 '15 at 02:54
  • 1
    @user3467349 Ok - your code does what _python's `pop`_ does, not what Ruby's `Array#pop` does, or what `pop()` does in typical ordered structures, which is to pop the top element off a stack. The Ruby name for what Python does there is `Hash#delete`. – Michael Berkowski May 15 '15 at 02:57
  • I see... the `delete` method returns the value. That's not very intuitive. But I guess that answers my question. – user3467349 May 15 '15 at 02:58
  • Yep, it's kind of a misnomer. – Michael Berkowski May 15 '15 at 02:59

1 Answers1

14

If you know the key, just use delete directly if the hash doesn't contain the key, you will get nil back, otherwise you will get whatever was stored there

from the doc you linked to:

h = { "a" => 100, "b" => 200 }
h.delete("a")                              #=> 100
h.delete("z")                              #=> nil
h.delete("z") { |el| "#{el} not found" }   #=> "z not found"

There is also shift which deletes and returns a key-value pair:

hsh = Hash.new

hsh['bb'] = 42
hsh['aa'] = 23
hsh['cc'] = 65

p hsh.shift

=> ["bb", 42]

As can be seen, the order of a hash is the order of insertion, not the key or value. From the doc

Hashes enumerate their values in the order that the corresponding keys were inserted.

Björn Nilsson
  • 3,703
  • 1
  • 24
  • 29
  • Your code in the question does exactly the same as d.delete('a') so I'm not sure what you are trying to do. – Björn Nilsson May 15 '15 at 03:00
  • Yes I hadn't realized `delete` returned a value. – user3467349 May 15 '15 at 03:01
  • It's not completely obvious from the method name. There is also shift which behaves sort of like pop on an array where it deletes and returns a key-value pair – Björn Nilsson May 15 '15 at 03:06
  • What's the behaviour like for `shift` and `first` does it just return the first `key-val` pair it comes across or are the hash-tables actually ordered in some way? – user3467349 May 15 '15 at 03:09
  • The short answer is that hashes behaves like arrays in the sense that first/shift returns the element that was first inserted, but writing code that depends on it is bad. The order of hashes is an implementation detail. Your code becomes less clear and it might even behave differently in some Ruby implementations. If you want items in a certain order then use an array or sort them explicitly. See https://stackoverflow.com/a/31425274/813125 for more details. – Björn Nilsson Jun 20 '21 at 16:29