how to take a hash and turn into an array - ruby-on-rails

I want to be able to take the following:
{"6"=>"", "7"=>"104", "8"=>"", "9"=>"", "0"=>"Testing", "2"=>"1", "3"=>"", "10"=>"Testing", "4"=>"1", "5"=>""}
and convert it into
[["","104","","","Testing"........], ["" ......]
Thank you

The Hash class has the method values which returns an array of all the values.
my_hash = {"6" => "", "7" => "104"}
my_array_of_values = my_hash.values # ["", "104"]
In Ruby, the Hash contains key/value pairs (eg. { key => value }). The keys method returns an array of the keys and the values method returns an array of the values.
Read more about the values method here:
http://ruby-doc.org/core/classes/Hash.html#M002867

Related

Taking values from a Ruby array of hashes

I have an array of hashes:
a = [{"Key1"=>"Value1", "Key2"=>"Value2"},
{"Key1"=>"Value3", "Key2"=>"Value4"},
{"Key1"=>"Value5", "Key2"=>"Value6"}]
Basically I am trying to get an output with only values and not any keys. Something like this
['Value1', 'Value2', 'Value3', 'Value4', 'Value5', 'Value6']
Here is the code which I tried. As key1 and key2 are the same, I stored both the keys in an array....
k = ["key1", "key2"]
for i in 0..a.length
k.each do |key_to_delete|
a[i].delete key_to_delete unless a[i].nil?
end
end
However, this removes all values and I get an empty array. Any help is appreciated.
You can use Enumerable#flat_map and fetch values from each hash:
a.flat_map(&:values)
=> ["Value1", "Value2", "Value3", "Value4", "Value5", "Value6"]
This is an answer on the original question.

match key of hash and then fetch values accordingly in ruby

I have included the given code:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test] #I get "1,3,7"
I get this, now please guide me how to match keys with #amaze and accordingly fetch its values from #classes i.e USA, France, Delhi.
Since #amaze is just a String, lets first convert it in Array so its easy to enumerate:
#amaze = "1,3,7"
#amaze = #amaze.split(",")
# => ["1", "3", "7"]
Now, since you have all keys extract all values:
#amaze.map { |i| #classes[i.to_i] }
# => ["USA", "France", "Delhi"]
Split #amaze by , and get an array of keys, convert them into Integer, then select only those key/value pairs which key is into this array of keys. Something like this:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = "1,3,7" #I get "1,3,7"
arr = #amaze.split(',').map(&:to_i)
p #classes.select{|el| arr.include? el}
Result:
#> {1=>"USA", 3=>"France", 7=>"Delhi"}
If you want values only use .values:
p #classes.select{|el| arr.include? el}.values
Result:
#> ["USA", "France", "Delhi"]
For what(seemingly) you are asking, the below line will do it:
#amaze.split(",").each { |i| p #classes[i.to_i] }
# If #amaza = "1,3,7", above line will output:
# => "USA"
# "France"
# "UK"
This should work well for you:
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
#amaze = params[:test].split(",").map(&:to_i)
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi"]
Hash#values_at accepts an indefinite number of keys and returns their values as an array. The * (splat) operator explodes the array so this call actually becomes #classes.values_at(1,3,7) Docs
Might also want to add a compact to the end in the event a key does not exist. e.g
#amaze = params[:test].split(",").map(&:to_i) # Asssume this returns [1,3,7,9]
#classes.values_at(*#amaze)
#=> ["USA", "France", "Delhi",nil]
#classes.values_at(*#amaze).compact
#=> ["USA", "France", "Delhi"]
I think a clearer understanding of hashes would help you out here.
A Hash is a data structure that is a list of key-value pairs. For example, the following is a Hash object of key-value pairs (your example):
#classes = {1=>"USA", 3=>"France", 2=>"UK", 5=>"Europe", 7=>"Delhi", 8=>"test"}
If you want to extract a value from #classes, you need to pass the key of the value you want. If we wanted "USA" we would pass the key of 1 to #classes. If we wanted "France", we would pass it the key of 3:
#classes[1] would return "USA" and #classes[3] would return "France".
It's not clear what data structure #amaze is according to your question, but let's say it's the string "1, 3, 7" which we can split to create an array [1, 3, 7].
You could iterate over the array to get each of the values from #classes:
#amaze.split(",").map(&:to_i).each do |key|
puts #classes[key]
end
That would print out each of the corresponding values to keys in #classes.

how do I invert my hash (switch key/value) and group by value

I have a hash in rails like so:
{"unique_id" => "1",
"unique_id2" => "2",
"unique_id3" => "n"}
Each unique key has a count that can be a number 1-20. What I would like to do is have a hash that looks like this:
{"1" => ["unique_id", "unique_id2"],
"2" => ["unique_id3"],
"3" => ["unique_id4", "unique_id5", "uniqueid6"]}
How would I go about doing that with a hash?
Not too hard!
hash = { "unique_id" => "1",
"unique_id2" => "2",
"unique_id3" => "n"
}
new_hash = hash.each_with_object({}) { |(k,v), h| (h[v] ||= []) << k }
each_with_object({}) is just an each loop with a blank hash
||= [] means if the hash doesn't have a value for v, set it equal to an empty array
<< k pushes the key onto the array
Try this:
h.group_by{|k,v| v }.each{|k,v| v.map!(&:first) }
group_by takes your hash and groups it by value
each iterates over the result hash
map! maps the first elements of the result value arrays, since group_by on a Hash returns two-dimensional Arrays with the structure [key, value]

How to insert an array to an existing hash array in Ruby?

I have a current array of the below hash map, i have another array that i would like to insert into each hash by matching on the id.
{"url"=>"http://ubuntu64:1990/getpages",
"id"=>"32794",
"version"=>"2",
"title"=>"Creating a page",
"space"=>"test",
"parentId"=>"32782",
"permissions"=>"0"}
The other array i want to add the 'imageurl' key/value based on the id, so something like (if id == id insert 'imageurl'/'someurl.jpg}
{"id"=>"32794", "imageurl" => "someurl.jpg}
array = [...] #Declare your array with the "big" hashes here
array2 = [...] #Declare your array with the hash containing the imageurl key here
array.each do |a|
array2.each do |a2|
if a[:id] == a2[:id]
a[:imageurl] = a2[:imageurl]
break #We found it
end
end
end
Should do the trick ... maybe there's a smarter way to do it though

push new element into array within hash

I have a hash which, I have keys that uniquely identify each element within the hash. And within each element, I have an array. So my question is, how do I put another element inside that array within the hash.
{"Apple"=>[1, 5.99], "Banana"=>[5, 9.99]}
I'm looping through a result set, and I'm a little bit lost how to add another element to the array...
If your hash is called, for example, hsh, then the "Apple" array can be accessed by hsh["Apple"]. You can use this like any variable, so to add a value to that array just do hsh["Apple"] << some_value. Like so:
irb> hsh = { "Apple" => [1, 5.99], "Banana" => [5, 9.99] }
irb> hsh["Apple"] << 9999
=> { "Apple" => [1, 5.99, 9999], "Banana" => [5, 9.99] }

Resources