How to combine two arrays of hashes? - ruby

I am querying an API to get information on users given their email address. For example:
emails = [{'email' => 'example1#test.com'}, {'email' => 'example2#test.com'}, ... ]
The query hash I pass to the API has to be in this format. The API returns an array of hashes on the information it found for each user. If there was no information it returns an empty hash in that index. The results are returned in the same order as they are queried, i.e. the first index of the response array is the info for example1#test.com. A sample response might look like this:
response = [{'gender' => 'male', 'age' => '24 - 35'}, {'gender' => 'male'}, ... ]
How can I combine my array of email hashes with the response array such that I will get something like the following?
combined = [
{'email' => 'example1#test.com', 'gender' => 'male', 'age' => '24 - 35'},
{'email' => 'example2#test.com', 'gender' => 'male'}, ... ]

The other way to achieve this, basing on #Arup Rakshit's answer:
emails = [{'email' => 'example1#test.com'}, {'email' => 'example2#test.com'} ]
response = [{'gender' => 'male', 'age' => '24 - 35'}, {'gender' => 'male'}]
emails.map.with_index { |hash, i| hash.merge(response[i]) }

How is this?
emails = [{'email' => 'example1#test.com'}, {'email' => 'example2#test.com'} ]
response = [{'gender' => 'male', 'age' => '24 - 35'}, {'gender' => 'male'}]
combined = emails.each_index.map { |i| emails[i].merge(response[i]) }

My version using Array#zip:
emails = [{'email' => 'example1#test.com'}, {'email' => 'example2#test.com'}]
response = [{'gender' => 'male', 'age' => '24 - 35'}, {'gender' => 'male'}]
combined = emails.zip(response).map { |e, r| e.merge(r) }
# => [{"email"=>"example1#test.com", "gender"=>"male", "age"=>"24 - 35"},
# {"email"=>"example2#test.com", "gender"=>"male"}]

Related

Concatenating two arrays and sum with keys via Laravel Collection

I'm having a set of array in something like this format:
[
{"GA_1":"1","GA_2":null,"GA_3":null,"GA_4":null},
{"SA_1":null,"SA_2":"2","SA_3":null,"SA_4":null},
{"RA_1":"1","RA_2":null,"RA_3":null,"RA_4":null}
]
I'm storing this in my mysql text column in json_decoded format. I want to call all the eloquent models and merge these arrays with sum of the each keys on object. For example
1st row contains:
[
{"GA_1":"1","GA_2":null,"GA_3":null,"GA_4":null},
{"SA_1":null,"SA_2":"2","SA_3":null,"SA_4":null},
{"RA_1":"1","RA_2":null,"RA_3":null,"RA_4":null}
]
2nd row contains:
[
{"GA_1":null,"GA_2":"1","GA_3":"2","GA_4":null},
{"SA_1":"1","SA_2":null,"SA_3":"3","SA_4":null},
{"RA_1":null,"RA_2":"2","RA_3":null,"RA_4":"5"}
]
3rd row contains:
[
{"GA_1":"1","GA_2":null,"GA_3":null,"GA_4":null},
{"SA_1":null,"SA_2":"2","SA_3":null,"SA_4":null},
{"RA_1":"1","RA_2":null,"RA_3":null,"RA_4":null}
]
so my final output should be:
[
{"GA_1":"2","GA_2":"1","GA_3":"2","GA_4":null},
{"SA_1":"1","SA_2":"4","SA_3":null,"SA_4":null},
{"RA_1":"1","RA_2":"2","RA_3":null,"RA_4":"5"}
]
I'm stuck in how can I achieve this:
$games = Game::get();
$grid = [];
foreach ($games as $game) {
$grid[] = collect($game->grid_values);
}
dd(collect('$grid')->flatten());
I'm getting this output:
Any suggestions are welcome. Thanks.
Well I tried something like this:
$games = Game::get();
$d = collect($games)->map(function($item) {
return json_decode($item->grid_values);
})->flatten();
$x = collect([
[
'GA_1' => $d->sum('GA_1'),
'GA_2' => $d->sum('GA_2'),
'GA_3' => $d->sum('GA_3'),
'GA_4' => $d->sum('GA_4'),
'GA_5' => $d->sum('GA_5'),
'GA_6' => $d->sum('GA_6'),
'GA_7' => $d->sum('GA_7'),
'GA_8' => $d->sum('GA_8'),
'GA_9' => $d->sum('GA_9'),
'GA_0' => $d->sum('GA_0'),
],
[
'SA_1' => $d->sum('SA_1'),
'SA_2' => $d->sum('SA_2'),
'SA_3' => $d->sum('SA_3'),
'SA_4' => $d->sum('SA_4'),
'SA_5' => $d->sum('SA_5'),
'SA_6' => $d->sum('SA_6'),
'SA_7' => $d->sum('SA_7'),
'SA_8' => $d->sum('SA_8'),
'SA_9' => $d->sum('SA_9'),
'SA_0' => $d->sum('SA_0'),
],
[
'RA_1' => $d->sum('RA_1'),
'RA_2' => $d->sum('RA_2'),
'RA_3' => $d->sum('RA_3'),
'RA_4' => $d->sum('RA_4'),
'RA_5' => $d->sum('RA_5'),
'RA_6' => $d->sum('RA_6'),
'RA_7' => $d->sum('RA_7'),
'RA_8' => $d->sum('RA_8'),
'RA_9' => $d->sum('RA_9'),
'RA_0' => $d->sum('RA_0'),
],
]);
return response()->json(['data' => $x], 200);
And I got expected result, any improvisation please suggest.

Create multi-dimensional array or hash in ruby from JSON

I am using Rhomobile and trying to dynamically build a hash for the id and title of the buttons has of the Alert.show_popup, but am not quite getting it. What I want the end result to be, in effect, is:
Alert.show_popup( {
:message => 'Please Select Appropriate Address:',
:title => 'Get Nearby...',
:icon => :info,
:buttons => [
{'id' => '1', 'title' => 'Address 1'},
{'id' => '2', 'title' => 'Address 2'},
{'id' => '3', 'title' => 'Address 3'},
{'id' => '4', 'title' => 'Address 4'}
],
:callback => url_for(:action => :on_addressidentified_popup)
}
)
I've tried a few methods, but none have worked (build a string that looks like a hash and try_convert, etc.). Here was the latest one I tried which seemed close, but yet still far away:
nearbyaddresses = Rho::JSON.parse(#params['body'])
h = {}
nearbyaddresses.each do |location|
h[intIndex] = {}
h[intIndex][:id] = intIndex.to_s
h[intIndex][:title] = location["Address"].to_s
intIndex = intIndex + 1
end
Alert.show_popup( {
:message => 'Please Select Appropriate Address:',
:title => 'Get Nearby...',
:icon => :info,
:buttons => h,
:callback => url_for(:action => :on_addressidentified_popup)
}
)
Any ruby wizards here that can help me out?
How about
nearby_addresses_list = Rho::JSON.parse(#params['body'])
buttons_list = nearby_addresses_list.collect.each_with_index {|address, i|
{'id' => i, 'title' => address} #not sure if you need to dig into this at all.
}
This should leave buttons_list with this value
[{'id' => 0, 'title' => nearby_addresses_list[0]},
{'id' => 1, 'title' => nearby_addresses_list[1]}
{'id' => 2, 'title' => nearby_addresses_list[2]}
{'id' => 3, 'title' => nearby_addresses_list[3]}]
If you want the id's to start with 1, change the body of the collect statement to {'id' => i+1, 'title' => address}
Then just add buttons_list in as the value for the key :buttons.
Alert.show_popup( {
:message => 'Please Select Appropriate Address:',
:title => 'Get Nearby...',
:icon => :info,
:buttons => buttons_list,
:callback => url_for(:action => :on_addressidentified_popup)
})
If you're seeing weirdness between the desired output you mentioned first and the code you said was close, is it perhaps that you used symbols for the keys in your code (:id), and strings in your desired output ("id") ?
Here's how I addressed the issue. Works like a charm...
intIndex = 0
nearbyaddresses = Rho::JSON.parse(#params['body'])
##nearbyAddresses = nearbyaddresses
button_array = []
nearbyaddresses.each do |location|
opt = {'id' => intIndex.to_s, 'title' => location["Address"] }
button_array << opt
intIndex = intIndex + 1
end
Alert.show_popup( {
:message => 'Please Select Appropriate Address:',
:title => 'Get Nearby...',
:icon => :info,
:buttons => button_array,
:callback => url_for(:action => :getselectedaddress)
}
)

Array nested in hash for WP API?

Here's my call:
result = blog.call('wp.newPost',
1,
'user',
'pw',
{
'post_type' => 'post',
'post_content' => entry[3],
'post_name' => entry[2].downcase.split(" ").join("-"),
'comment_status' => 'closed',
'pinged' => 'closed',
'post_status' => 'publish',
'post_title' => entry[2],
'terms' => ['category' => 9]
})
This is returning an error that this post type post doesn't support one of the taxonomies given category - well, every post should have a category, so I'm thinking that my ruby is malformed. The API asks for an array with the taxonomy as a key and its ID as the value, which I think I've done here.
This is for v3.4 - here is the documentation on wp.newPost
Interestingly enough, the following code worked:
blogcontent = {
:post_type => 'post',
:post_content => entry[3],
:post_name => entry[2].downcase.split(" ").join("-"),
:comment_status => 'closed',
:pinged => 'closed',
:post_status => 'publish',
:post_title => entry[2],
:terms =>
{
:category => [9]
}
}
This converted (via the XMLRPC Writer) to the appropriate XML and registered the posts in WordPress. Turning on the XML-RPC debugging information revealed that a struct wasn't being passed unless the variable 9 was enclosed in brackets, even though it is a single value array.

Getting key value in nested Hash by key array values

Sample hash:
{
"audio" => {
"audio/aac" => ["aac"],
"audio/mpeg" => ["mp3", "mp2"],
"audio/mp4" => ["m4a", "m4b", "m4r", "3gp"],
"audio/ogg" => ["ogg", "oga"],
"audio/flac" => ["flac"],
"audio/speex" => ["spx"],
"audio/x-ms-wma" => ["wma"],
"audio/x-pn-realaudio" => ["rm", "ram"],
"audio/vnd.wave" => ["wav"],
"audio/x-musepack" => ["mpc", "mp+", "mpp"],
"audio/x-aiff" => ["aiff", "aif", "aifc"],
"audio/x-tta" => ["tta"]
},
"video" => {
"video/mp4" => ["mp4"],
"video/mpeg" => ["mpg", "mpeg"],
"video/x-m4v" => ["m4v"],
"video/quicktime" => ["mov"],
"video/x-msvideo" => ["avi"],
"video/x-flv" => ["flv"],
"video/webm" => ["webm"]
}
}
What's the best way given a file extension to get the associated content type (first match is okay)?
Searching for "flac" should return "audio/flac".
Currently I'm using this:
hsh.each_key do |group|
hsh[group].each do |k,v|
return k if v.include?(extension)
end
end
Unraveling that sort of structure is best done when it's created. But, you can loop through the various levels and get something useful from it. If I assign your initial hash to mime_hash I can unravel it using:
Hash[*mime_hash.map{ |av, types| types.map{ |mime_type, extensions| extensions.product([mime_type]) } }.flatten]
or more verbosely:
Hash[
*mime_hash.map{ |av, types|
types.map{ |mime_type, extensions|
extensions.product([mime_type])
}
}.flatten
]
Which will return:
{
"aac" => "audio/aac",
"mp3" => "audio/mpeg",
"mp2" => "audio/mpeg",
"m4a" => "audio/mp4",
"m4b" => "audio/mp4",
"m4r" => "audio/mp4",
"3gp" => "audio/mp4",
"ogg" => "audio/ogg",
"oga" => "audio/ogg",
"flac" => "audio/flac",
"spx" => "audio/speex",
"wma" => "audio/x-ms-wma",
"rm" => "audio/x-pn-realaudio",
"ram" => "audio/x-pn-realaudio",
"wav" => "audio/vnd.wave",
"mpc" => "audio/x-musepack",
"mp+" => "audio/x-musepack",
"mpp" => "audio/x-musepack",
"aiff" => "audio/x-aiff",
"aif" => "audio/x-aiff",
"aifc" => "audio/x-aiff",
"tta" => "audio/x-tta",
"mp4" => "video/mp4",
"mpg" => "video/mpeg",
"mpeg" => "video/mpeg",
"m4v" => "video/x-m4v",
"mov" => "video/quicktime",
"avi" => "video/x-msvideo",
"flv" => "video/x-flv",
"webm" => "video/webm"
}
As you've already realized the data structure you have is horrible to search in the fashion you want. Assuming you're going to be searching the same data over and over what you should do is create an index for it.
There are many ways of doing this but the simplest is probably just to flatten the hash and invert it so that your keys become values and vice-versa. That way you can simply search it by calling content_types['flac']
A section of the example hash might end up like this:
{
"aac" => "audio/aac",
"mp3" => "audio/mpeg",
"mp2" => "audio/mpeg",
"m4a" => "audio/mp4",
"m4b" => "audio/mp4",
"m4r" => "audio/mp4",
"3gp" => "audio/mp4",
"flac" => "audio/flac"
}
Try using rassoc()
Definition:
Searches through the hash comparing obj with the value using ==. Returns the first key-value pair (two-element array) that matches. See also Array#rassoc.
a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
a.rassoc("two") #=> [2, "two"]
a.rassoc("four") #=> nil

Using Typhoeus to POST an array to a URL

I'm using Typhoeus to post a hash to my API url. It's actually an array containing a set of hashes. Here's effectively what I'm doing:
companies = Array.new
company = { 'name' => 'Company 1' , 'company_url' => 'http://company.com' }
companies.push(company)
company2 = {'name' => 'Company 2' , 'company_url' => 'http://company2.com' }
companies.push(company2)
request = Typhoeus::Request.post("http://myapi.com/1.0/startups/create_batch",
:username => 'user',
:password => 'password',
:auth_method => :basic,
:params => {'companies' => companies} )
print "Create_batch response "+request.body
Once I run the script I get the output which states "Create_batch response Disallowed Key Characters.". I'm not sure what it's referencing at this point. I've looked over the text output of what print companies shows up but I don't see any strange code.
Anybody have any insights on what I should do?

Resources