Insert in multiple arrays, in hash with key values in ruby - ruby

array1 = [[a,b,c],[1,2,3],[x,y,z]]
array2 = [[1,2,1],[2,2,2],[a,a,a]]
array3 = [[d,d,d], {a=>1,b=>2}]
#keys = key1,key2,key3
i need to to show the one single hash in below format
output = {"key1" => [[a,b,c],[1,2,3],[x,y,z]], "key2" => [[1,2,1],[2,2,2],[a,a,a]], "key3" => [[d,d,d], {a=>1,b=>2}] }
i am tried to in this code
Hash[#key.zip(array1)]

Multiple variables can't be manipulated as easily as elements in, say, an array. The easiest way to produce desired output in your case is to just write it out manually.
output = {
key1: array1,
key2: array2,
key3: array3,
}
If you want to be more dynamic, put your arrays into a usable data structure. Then you can use .zip or whatever.
keys = [:key1, :key2, :key3]
usable_arrays = [array1, array2, array3]
Hash[keys.zip(usable_arrays)]

Related

Understanding map in Ruby

I'm pretty new to Ruby and am trying to understand an example of the map method that I came across:
{:a => "foo", :b => "bar"}.map{|a, b| "#{a}=#{b}"}.join('&')
which returns:
=> "a=foo&b=bar"
I don't understand how the
b=bar
is returned. The string interpolation is what is confusing me as it seems it would return something like:
=> "a=foo&bbar"
> {:a => "foo", :b => "bar"}.map{|key, value| "#{key}=#{value}"}
#=> ["a=foo", "b=bar"]
map method will fetch each element of hash as key and value pair
"#{key}=#{value}" is a String Interpolation which adds = between your key and value
Using this syntax everything between the opening #{ and closing } bits
is evaluated as Ruby code, and the result of this evaluation will be
embedded into the string surrounding it.
Array#join will returns a string created by converting each element of the array to a string, separated by the given separator.
so here in your case:
> ["a=foo", "b=bar"].join('&')
#=> "a=foo&b=bar"
In Rails you can convert hash to query params using Hash#to_query method, which will return the same result.
> {:a => "foo", :b => "bar"}.to_query
#=> "a=foo&b=bar"
The symbol key :a and the local variable a have nothing in common. The names are only coincidentally the same. Consider this code instead:
{
var1: "value1",
var2: "value2"
}.map do |key, value|
"#{key}=#{value}"
end.join('&')
# => "var1=value1&var2=value2"
Here the variables are different. What map does, like each, is iterate over each key-value pair in the Hash. That means you can do things like this, too, to simplify:
{
var1: "value1",
var2: "value2"
}.map do |pair|
pair.join('=')
end.join('&')
# => "var1=value1&var2=value2"
Normally when iterating over a Hash you should use names like k,v or key,value to be clear on what you're operating on.
If you're ever confused what's going on internally in an iteration loop, you can debug like this:
{
var1: "value1",
var2: "value2"
}.map do |pair|
puts pair.inspect
pair.join('=')
end.join('&')
That gives you this output:
[:var1, "value1"]
[:var2, "value2"]
That technique helps a lot. There's even the short-hand notation for this:
p pair
There are 2 method calls occurring here, the map and the join. One way to make it clearer and easier to understand is to separate the two methods and alter the keywords used in the map method. So instead of
{:a => "foo", :b => "bar"}.map{|a, b| "#{a}=#{b}"}.join('&')
Lets have
{:a => "foo", :b => "bar"}.map{|key, value| "#{key}=#{value}"}
This returns an array. #=> ["a=foo", "b=bar"]
Now:
["a=foo", "b=bar"].join('&')
produces a sting
#=> "a=foo&b=bar"
Map is iterating over the two key/value pairs and creating a string with the '=' between them and returns it in an array. It would iterate over all the key/value pairs in the harsh. Our example just has 2.
Join attaches the two elements of the array together with the '&' symbol between them and returns it as string. It would attach all elements of the array no matter its size.
What helped me to learn map and join is to open up the irb or pry and create a few hashes and arrays and play around with them. I highly recommend using unique names for your values that explain what is going on.
I hope this helps you.

Converting Setting File to Hash

I have a settings file and I am reading it with file read and getting a string that I want to convert into a hash for easier usage.
How can I convert the following:
string="key1=value1\nkey2=value2"
Into:
{"key1" => "value1", "key2" => "value2"}
You can do this:
string.split("\n").map{|s| s.split("=")}.to_h
First split around new lines.
string.split("\n")
#=> ["key1=value1", "key2=v vlue2"]
Next, split each strings around =
string.split("\n").map{|s| s.split("=")}
#=> [["key1", "value1"], ["key2", "v vlue2"]]
Next, convert the array of 2-element arrays into Hash by calling to_h method.
string.split("\n").map{|s| s.split("=")}.to_h
#=> {"key1"=>"value1", "key2"=>"v vlue2"}
Hash[*string.split(/[\n=]/)] # => {"key1"=>"value1", "key2"=>"value2"}

Whats the ruby way to extract an array of values from an array of hashes?

Suppose I have an array like this:
starting_array = [{key1: 'someKey1Value', key2: 'someKey2Value'}, {key1: 'anotherKey1Value', key2: 'anotherKey2Value'}]
I want to end up with this:
desired_array = ['someKey2Value', 'anotherKey2Value']
Whats the best way to extract all the values for key2 into a separate array?
Use Array#map :-
starting_array.map { |hash| hash[:key2] }

Find difference between arrays in Ruby, where the elements are hashes

I have two arrays of hashes I would like to find the difference between. My issue is the array elements are single item hashes.
So far, using array1 - array2 appears to be working correctly but do I need to watch out for gotchas here? The hash elements themselves read like h = {'ID' => '76322'}, where the numeric value differs from hash to hash, so nothing too fancy.
[EDIT]
Here's what I'm looking for:
array1 = []
array2 = []
h = {'ID' => '76322'}
array1.push(h)
h = {'ID' => '7891'}
array1.push(h)
array2.push(h)
array1 = array1 - array2 # should result in array1 having a single hash of values {'ID', '76322'}
array1 - array2 works by putting the elements of array2 into a temporary hash, then returning all elements of array1 that don't appear in the hash. Hash elements are compared using == to determine whether they match.
Comparing two hashes with == gives true if all the keys and values of the hashes match using ==. So
h1 = {'ID' => '7891'}
h2 = {'ID' => '7891'}
h1 == h2
evaluates to true, even though h1 and h2 are different hashes, and the corresponding elements will be correctly removed.
The only consideration I can think of is if you always have strings everywhere in the hash keys and values. If they are sometimes integers, or symbols, like {:ID => 7891} then you aren't going to get the results you want, because :ID == 'ID' and '7891' == 7891 are both false.

Creating array of hashes in ruby

I want to create an array of hashes in ruby as:
arr[0]
"name": abc
"mobile_num" :9898989898
"email" :abc#xyz.com
arr[1]
"name": xyz
"mobile_num" :9698989898
"email" :abcd#xyz.com
I have seen hash and array documentation. In all I found, I have to do something
like
c = {}
c["name"] = "abc"
c["mobile_num"] = 9898989898
c["email"] = "abc#xyz.com"
arr << c
Iterating as in above statements in loop allows me to fill arr. I actually rowofrows with one row like ["abc",9898989898,"abc#xyz.com"]. Is there any better way to do this?
Assuming what you mean by "rowofrows" is an array of arrays, heres a solution to what I think you're trying to accomplish:
array_of_arrays = [["abc",9898989898,"abc#xyz.com"], ["def",9898989898,"def#xyz.com"]]
array_of_hashes = []
array_of_arrays.each { |record| array_of_hashes << {'name' => record[0], 'number' => record[1].to_i, 'email' => record[2]} }
p array_of_hashes
Will output your array of hashes:
[{"name"=>"abc", "number"=>9898989898, "email"=>"abc#xyz.com"}, {"name"=>"def", "number"=>9898989898, "email"=>"def#xyz.com"}]
you can first define the array as
array = []
then you can define the hashes one by one as following and push them in the array.
hash1 = {:name => "mark" ,:age => 25}
and then do
array.push(hash1)
this will insert the hash into the array . Similarly you can push more hashes to create an array of hashes.
You could also do it directly within the push method like this:
First define your array:
#shopping_list_items = []
And add a new item to your list:
#shopping_list_items.push(description: "Apples", amount: 3)
Which will give you something like this:
=> [{:description=>"Apples", :amount=>3}]

Resources