Return a single key from a Hash? - ruby

I would like to know how to return a specific key from a Hash?
Example:
moves = Hash["Kick", 100, "Punch", 50]
How would I return the first key "Kick" from this Hash?
NOTE: I'm aware that the following function will return all keys from the hash but I'm just interested in returning one key.
moves.keys #=> ["Kick", "Punch"]

You can use:
first_key, first_value = moves.first
Or equivalently:
first_key = moves.first.first
Quite nice too:
first_key = moves.each_key.first
The other possibility, moves.keys.first will build an intermediary array for all keys which could potentially be very big.
Note that Ruby 1.8 makes no guarantee on the order of a hash, so the key you will get not always be the same. In Ruby 1.9, you will always get the same key ("Kick" in your example).

moves.keys[0]
will give you the first key.
You can get all keys by changing the argument passed (0, 1,...etc)

moves.keys.first will accomplish that.

Related

Get a value from an array of hashes in ruby

I have an array of hashes:
ary = [{1=>"January", 2=>"February", 3=>"March"}, {11=>"Oct", 12=>"Nov", 13=>"Dec"}]
How can I get the value from a particular hash, based on a key? I would like to do something like:
ary[1].select{|h| h[13]}
to get the value "Dec" from the second hash with the key 13. The above statement returns the whole second hash, which is not the requirement:
{11=>"Oct", 12=>"Nov", 13=>"Dec"}
The select statement will return all the hashes with the key 13.
If you already know which hash has the key then the below code will give u the answer.
ary[1][13]
However if you are not sure which of your hashes in the array has the value, then you could do the following:
values = ary.map{|h| h[13]}.compact
Values will have the value of key 13 from all the hashes which has the key 13.
You can merge the two hashes in one and then query the keys of the merged hash.
c = a.merge(b)
=> {1=>"January", 2=>"February", 3=>"March", 11=>"Oct", 12=>"Nov", 13=>"Dec"}
And then you can do something like:
c[1]
=> "January"
Otherwise, if you want to keep the format as an array of different hashes you can just get the value you want this way:
ary[1][12]
=> "Nov"
But that way you have to always know in which hash inside the array is the element you want, which seems a bit confusing because you could just use different hashes instead of an array of hashes and having to remember each hash's position inside the array.
Firstly make a single hash and then return the value of hash by key.
Make single hash from array with merging elements.
Method 1
hash = ary.reduce({}, :merge)
Method 2
hash = ary.inject(:merge)
Then return the value by key.
hash[13]

Better way to loop through a set of hashes assigning array values in Ruby

I am trying to insert data into Postgres. I have an array of data and I am trying to assign each column a value of the array. Here is an example.
pg_insert = ['12/09/2015', 41, 'test account', '41.0']
Table.create([date: pg_insert[0],
account_number: pg_insert[1],
account_name: pg_insert[2],
values: pg_insert[3]])
Is there a way where I can loop this so I can put i in pg_insert instead of having to type out numbers? I'm not sure how to loop inside of the create() parameter. Is there any way around this?
Any suggestions would be great thanks.
Table.create is accepting a Hash, I'm sure.
So here is what you can do:
Make an Array called keys that contains 4 symbols :date, :account_number, :account_name, and :values.
pg_insert is already an Array.
Now you can put the two Arrays together to make the Hash you need: Hash[keys.zip(pg_insert)]
This allows you to call Table.create like this: Table.create(Hash[keys.zip(pg_insert)])
Here is the finished code then:
keys = [:date, :account_number, :account_name, :values]
pg_insert = ['12/09/2015', 41, 'test account', '41.0']
Table.create(Hash[keys.zip(pg_insert)]) # or Table.create Hash[keys.zip(pg_insert)] if you don't want so many parentheses.
Note that pg_insert will always have to be in the same order as keys.
You can read more about Array#zip and Hash.new to understand how those work. This SO link might also be helpful: Converting an array of keys and an array of values into a hash in Ruby

How to check if nested hash attributes are empty

I have a Hash
person_params = {"firstname"=>"",
"lastname"=>"tom123",
"addresses_attributes"=>
{"0"=>
{"address_type"=>"main",
"catalog_delivery"=>"0",
"street"=>"tomstr",
"city"=>"tomcity"
}
}
}
With person_params[:addresses_attributes], I get:
# => {"0"=>{"address_type"=>"main", "catalog_delivery"=>"0", "street"=>"tomstr", "zip"=>"", "lockbox"=>"", "city"=>"tomcity", "country"=>""}}
1) How can I get a new hash without the leading 0?
desired_hash = {"address_type"=>"main", "catalog_delivery"=>"0", "street"=>"tomstr", "zip"=>"", "lockbox"=>"", "city"=>"tomcity", "country"=>""}
2) How can I check whether the attributes in the new hash are empty?
Answer 1:
person_params[:addresses_attributes]['0']
Answer 2:
hash = person_params[:addresses_attributes]['0']
hash.empty?
This looks just like a params hash from Rails =D. Anyway, it seems that your addresses_attributes contains some nested attributes. This means that what you have in practice is more of an array of hashes than a single hash, and that's what you see right? Instead of it being an actually Ruby Array, it is a hash with the index as a string.
So how do you get the address attributes? Well if you only want to get the first address, here are some ways to do that:
person_params[:addresses_attributes].values.first
# OR
person_params[:addresses_attributes]["0"]
In the first case, we will just take the values from the addreses_attributes hash, which gives us an Array from which we can take the first item. If there are no values in addresses_attributes, then we will get nil.
In the second case, we will just ask for the hash value with the key "0". If there are no values in addresses_attributes, we will get nil with this method also. (You might want to avoid using the second case, if you are not confident that the addresses_attributes hash will always be indexed from "0" and incremented by "1")

Sort in ruby a JSON array of hashes

So I have an array of hashes:
[{"id":"30","name":"Dave"},
{"id":"57","name":"Mike"},
{"id":"9","name":"Kevin"},
...
{"id":"1","name":"Steve"}]
And I want to sort it by the id attribute, so that it looks like this:
[{"id":"1","name":"Steve"},
{"id":"2","name":"Walter"},
...
{"id":"60","name":"Chester"}]
I'm assuming I use the sort_by method but I'm not exactly sure how to do it.
This should work:
array.sort_by { |hash| hash['id'].to_i }
In this case, sort_by is preferred over sort because it is more efficient. While sort calls to_i on every comparison, sort_by does it once for each element in array and remembers the result.
When I see incoming data like that, it's almost always a JSON string. Ruby doesn't automatically understand JSON, nor does it automatically know how to convert it, but Ruby does make it easy for us to convert from/to it:
require 'json'
json_data = '[{"id":"30","name":"Dave"},
{"id":"57","name":"Mike"},
{"id":"9","name":"Kevin"},
{"id":"1","name":"Steve"}]'
ary = JSON[json_data].sort_by{ |e| e['id'].to_i }
ary
# => [{"id"=>"1", "name"=>"Steve"}, {"id"=>"9", "name"=>"Kevin"}, {"id"=>"30", "name"=>"Dave"}, {"id"=>"57", "name"=>"Mike"}]
The only real trick here is:
JSON[json_data]
A lot of time you'll see people use JSON.parse(json_data), but the [] method is smart enough to recognize whether it's getting a String or an array or a hash. If it's a string it tries to parse it assuming it's incoming data. If it's an array or a hash, it converts it to a JSON string for output. The result is, using JSON[...] simplifies the use of the class and makes it so we don't have to use parse or to_json.
Otherwise, using sort_by is preferred over using sort unless you are directly comparing two simple variables, like integer to integer, string to string or character to character. Once you have to dive into an object, or do some sort of calculation to determine how things compare, then you should use sort_by. See Wikipedia's article on Schwartzian Transform to understand what's going on under the covers. It's a very powerful technique that can speed up sorting remarkably.
Your Hash syntax is wrong, if they where symbols then it would look like this:
data = [
{id:"30", name:"Dave"},
{id:"57", name:"Mike"},
{id:"9", name:"Kevin"},
{id:"1", name:"Steve"}
]
sorted_data = data.sort_by{|x| x[:id].to_i}
Edit: Forgot the to_i, fixed. If the keys are strings the : way of defining a hash does not work, so we need hash-rockets instead:
data = [{"id"=>"30","name"=>"Dave"},
{"id"=>"57","name"=>"Mike"},
{"id"=>"9","name"=>"Kevin"},
{"id"=>"1","name"=>"Steve"}]
sorted_data = data.sort_by{|x| x['id'].to_i}

Sort a hash Ruby

I have a hash that looks like this
h1 = {"4c09a0da6071a593f051de32"=>["4c09a0da6071a593f051de32", "Cafe Bistro", 37.78458803130115, -122.40743637084961, 215.0], "4abbb03ef964a520668420e3"=>["4abbb03ef964a520668420e3", "The Plant Cafe Organic", 37.7977805076241, -122.3957633972168, 83.0] }
I would like to sort it by the final value in each hash e.g. 83.0, 215.0
I have tried
h1 = h1.sort_by{|k,v| v[4]}
but in out puts an array not a hash, i would like to keep the hash the same just reordered... how do I do this?
It's not a great idea to count on ordering in a Hash. Ruby didn't order hashes at all in 1.8. The data structure in its canonical form is not ordered.
It's better style to use an Array when ordering is important and a Hash or something else when key lookup is needed.
There is a grey area when writing tests. In that case, it may be reasonable to depend on Hash ordering since you are testing a specific Ruby program in certain conditions and you have, after all, a test that can fail should the implementation assumptions ever change.
You need to convert the array back to a hash:
h1 = Hash[h1.sort_by { |_,v| v[-1] }]
Note that this only works since Ruby 1.9. Before that, hashes were not an ordered data structure.

Resources