简体   繁体   中英

Hashes, arrays, and the ruby '.first' method

I am working on an Rails API that receives POSTed json input and processes things accordingly. The current element involves prizes and prize codes, and I have a question about hashes, arrays, and the ruby .first method.

Disclaimer: I am receiving json from a legacy PHP application and as of right now I don't have a way to edit the output from that application. I'm getting it as is and am dealing with it the best I can.

The prize codes are coming in as a nested element within a larger object, but we are just going to focus on the codes for now. Here's what I'm getting:

"codes" => {
  "0"=>{"Code"=>"1582566"},
  "1"=>{"Code"=>"2153094"},
  "2"=>{"Code"=>"3968052"},
  "3"=>{"Code"=>"4702730"},
  "4"=>{"Code"=>"5582567"},
  "5"=>{"Code"=>"6153097"},
  "6"=>{"Code"=>"7968052"},
  "7"=>{"Code"=>"8702730"},
  "8"=>{"Code"=>"9582567"},
  "9"=>{"Code"=>"1053097"}
}

Starting there, everything gets pulled into a block, and then I am dealing with each code individually.

I'm going to start with my final solution and we will work our way backwards. In order to get a single code, just the number, out of each code, this is my solution:

code[1].first.second.to_i returns 1582566

Now let's rewind, and start at the beginning.

code returns "0"=>{"Code"=>"1582566"}

That makes sense. Now I want to skip past that first level "0" .

code[1] returns {"Code"=>"1582566"}

All of that makes sense so far, but this is where things get weird. From that point I want to grab the 2nd item, maybe you might call it the value in this hashy key value pair. Unfortunately, the ruby .second doesn't work on a hash, I get an undefined method error, but .first does for some reason. And the output is confusing to me.

code[1].first returns ["Code", "4582566"]

And now all of a sudden that hash is an array. Why does the ruby .first array method turn a key value hash into an array?

I did a little sleuthing and discovered that :first is a method listed in the output from code[1].methods , but I can't seem to find any documentation out there about what it does.

code[1].class returns Hash

But then why do I get a completely different set of available methods returned when I run code[1].methods vs Hash.methods ? The :first method is listed in the output from code[1].methods but NOT in the output from Hash.methods and it is not on the list of available methods here either:

http://ruby-doc.org/core-2.1.5/Hash.html

If they are both Hashes, why are their different methods available? Does it have something to do with class methods vs instance methods?

I'm still confused about what exactly the .first method does to a hash.

In the end I realized a better / cleaner way to get what is code[1]['Code'].to_i , but I'm still curious about what is going on under the hood.

In Ruby, a Hash is an ordered collection of key/value pairs . We can say they are "ordered" because:

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

Because of this ordered enumeration, the Enumberable#first method returns the first key/value pair that was added to the hash as an Array of two items [key, value] .

{}.first # => nil
{1 => 2}.first # => [1, 2]
{:a => true, :b => false}.first # => [:a, true]
h = Hash.new
h[:m] = "n"
h[:o] = "p"
h.first # => [:m, "n"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM