New to ruby and I'm trying to create an array of hashes (or do I have it backwards?)
def collection
hash = { "firstname" => "Mark", "lastname" => "Martin", "age" => "24", "gender" => "M" }
array = []
array.push(hash)
#collection = array[0][:firstname]
end
#collection does not show the firstname for the object in position 0... What am I doing wrong?
Thanks in advance!
You're using a Symbol as the index into the Hash object that uses String objects as keys, so simply do this:
#collection = array[0]["firstname"]
I would encourage you to use Symbols as Hash keys rather than Strings because Symbols are cached, and therefore more efficient, so this would be a better solution:
def collection
hash = { :firstname => "Mark", :lastname => "Martin", :age => 24, :gender => "M" }
array = []
array.push(hash)
#collection = array[0][:firstname]
end
You have defined the keys of your hash as String. But then you are trying to reference it as Symbol. That won't work that way.
Try
#collection = array[0]["firstname"]
You can do this:
#collection = [{ "firstname" => "Mark", "lastname" => "Martin", "age" => "24", "gender" => "M" }]
Related
I have a hash that looks something like this:
hash = { "data" => {
"Aatrox" => {
"id" => "Aatrox",
"key" => "266",
"name" => "Aatrox"
},
"Ahri" => {
"id" => "Ahri",
"key" => "123",
"name" => "Ahri"
},
"Another name" => {
"id" => "Another name",
"key" => "12",
"name" => "Another name"
},
}
}
I'm trying to get the value from "id" that matches a given key:
def get_champion_name_from_id(key)
filtered = #champion_data["data"].select do | key, champ_data |
Integer(champ_data["key"]) == key
end
end
I'm using select to get the items that match the block, however, the return value is another hash that looks like this:
{
"Aatrox": {
"id" => "Aatrox",
"key" => "266",
"name" => "Aatrox"
}
}
How can I avoid this and get just the last nested hash?
If the key passed was 266, I want to get this hash:
{
"id" => "Aatrox",
"key" => "266",
"name" => "Aatrox"
}
This hash is the result of a parsed JSON file, so there's no way I can do filtered["Aatrox"] to get a given value.
Hash#values returns values only (without keys). And by using Enumerable#find, you will get the first matched item instead of an array that contains a single item.
#champion_data['data'].values.find { |champ_data|
champ_data['key'] == '266'
}
# => {"id"=>"Aatrox", "key"=>"266", "name"=>"Aatrox"}
def get_champion_name_from_id(key)
key = key.to_s
#champion_data['data'].values.find { |champ_data|
champ_data['key'] == key
}
end
You can do it with the select method also:
#champion_data["data"].select do |key, val|
#champion_data["data"][key] if #champion_data["data"][key]["key"] == "266"
end
I'm trying to concatenate the different "Name" values from the provided Hash into one string. So the output should be one array or string containing all "Name" values.
The difficulty for me sits in that the level of nesting varies between two and four parents.
I've tried to solve it in two ways:
Recursively go through the hash and on each level append the value to an array. Finally spit out the array.
Flatten the hash and then cherry pick from that array
Unfortunately none of the answers given in related questions seemed to work either. I'm sure it's quite simple but I can't seem to figure it out. Many thanks
my_hash = { "BreadCrumbs" => {
"Id" => 375,
"Name" => "Willingen",
"Parent" => {
"Id" => 52272,
"Name" => "Wintersport-Arena Sauerland",
"Parent" => {
"Id" => 8,
"Name" => "Germany"
}
}
}
}
▶ hash = { "BreadCrumbs" => {
▷ "Id" => 375,
▷ "Name" => "Willingen",
▷ "Parent" => {
▷ "Id" => 52272,
▷ "Name" => "Wintersport-Arena Sauerland",
▷ "Parent" => {
▷ "Id" => 8,
▷ "Name" => "Germany"
▷ }
▷ }
▷ }}
▶ def concat hash
▷ [hash['Name'], hash['Parent'] ? concat(hash['Parent']) : nil]
▷ end
▶ (concat hash['BreadCrumbs']).flatten.compact
#⇒ ["Willingen", "Wintersport-Arena Sauerland", "Germany"]
I do not flatten on every iteration so that the result still contains hierarchy:
▶ concat hash['BreadCrumbs']
#⇒ ["Willingen", ["Wintersport-Arena Sauerland", ["Germany", nil]]]
The requested string as the result:
▶ (concat hash['BreadCrumbs']).flatten.compact.join ', '
#⇒ "Willingen, Wintersport-Arena Sauerland, Germany"
For any number of levels, without using recursion:
def pull_names(hash)
h = hash
names = []
loop do
names << h["Name"]
return names unless h.key?("Parent")
h = h["Parent"]
end
end
Suppose:
hash = { "BreadCrumbs" => {
"Name" => "Willingen",
"Parent" => {
"Id" => 52272,
"Name" => "Wintersport-Arena Sauerland",
"Parent" => {
"Id" => 8,
"Name" => "Germany",
"Parent" => {
"Id" => 1,
"Name" => "Bora Bora"
}
}
}
}
}
then:
arr = pull_names hash["BreadCrumbs"]
#=> ["Willingen", "Wintersport-Arena Sauerland", "Germany", "Bora Bora"]
arr.join(' ')
#=> "Willingen Wintersport-Arena Sauerland Germany Bora Bora"
I have a hash passed by a user in puppet declaration and for the create_resources to use it, it needs to be added a new nested level with the key remaining to be the key but it's value being set to a nested hash in it with the values from the original value and some string.
like given this
hash = {
"Field1" => "Value11",
"Field2" => ["value1","value2"],
}
Then would like to have the new hash after that to be given as this output
hash = {
"Field1" => { "ensure" => "present",
"value" => "Value11",
},
"Field2" => { "ensure" => "present",
"value" => ["value1","value2"],
},
}
Tried to do
added = {'ensure' => 'present'}
hash.zip([added])
to no avail.
hash.each{|k, v| hash[k] = {"ensure" => "present", "value" => v}}
I'm trying to create different kind of structure from the array I currently have in my code.
I've got an array of objects (active directory objects) so lets say i got a from db :
a = [o1,o2,o3,o4,o5]
My object has property source_id and name which are the relevant properties.
I want to create structure like this (I want hash) from the data I have in my array :
objects = Hash.new { |hash, key| hash[key] = [] }
And this would be one example of how to put the data inside new structure:
a.each do |ob|
objects[ob.source_id] << {
:new => '',
:name => {:unformated => ob.name, :formatted => ob.format(:name)}
}
end
I'm trying to replicate the same structure and it's not working out in my case :
a.group_by(&:source_id).map do |k,v|
{
k=> {
{
:new => '',
:name => {:unformated => v.name, :formatted => ob.format(:name)}
}
}
}
end.reduce(:merge)
This is the error I get :
! #<NoMethodError: undefined method `name' for #<Array:0xae542b4>>
With group_by your values in the a.group_by(&:source_id).map are going to be arrays of elements sharing the same source_id and not individual elements.
The following code may do what you wish:
a.group_by(&:source_id).map do |k,v|
{
k => v.map do |e|
{
:new => '',
:name => {:unformated => e.name, :formatted => e.format(:name)}
}
end
}
end.reduce(:merge)
Heres a one liner to do the same
new_hash = a.each_with_object({}) { |o, hash| hash[o.source_id] = {:new => '', :unformatted => o.name, :formatted => o.format(:name)} }
This does require ruby 1.9.3 though
Here is what it looks like:
{
"groups" => [
{ "venues" => [
{ "city" => "Madrid",
"address" => "Camino de Perales, s/n",
"name" => "Caja Mágica",
"stats" => {"herenow"=>"0"},
"geolong" => -3.6894333,
"primarycategory" => {
"iconurl" => "http://foursquare.com/img/categories/arts_entertainment/stadium.png",
"fullpathname" => "Arts & Entertainment:Stadium",
"nodename" => "Stadium",
"id" => 78989 },
"geolat" => 40.375045,
"id" => 2492239,
"distance" => 0,
"state" => "Spain" }],
"type" => "Matching Places"}]
}
Big and ugly... I just want to grab the id out. How would I go about doing this?
h = { "groups" => ......... }
The two ids are:
h["groups"][0]["venues"][0]["primarycategory"]["id"]
h["groups"][0]["venues"][0]["id"]
If the hash stores one id:(assuming the value is stored in a variable called hash)
hash["groups"][0]["venues"][0]["primarycategory"]["id"] rescue nil
If the hash stores multiple ids then:
ids = Array(hash["groups"]).map do |g|
Array(g["venues"]).map do |v|
v["primarycategory"]["id"] rescue nil
end.compact
end.flatten
The ids holds the array of id's.