How can i get a hash into an array, state and acronym? - ruby

Array = [{:acronym => "AC", :fullname => "Acre"}, {:acronym => "AL", :fullname => "Alagoas"}, {:acronym => "AP", :fullname => "Amapá"}, {:acronym => "AM", :fullname => "Amazonas"}, {:acronym => "BA", :fullname => "Bahia"}, {:acronym => "CE", :fullname => "Ceará"}, {:acronym => "DF", :fullname => "Distrito Federal"}, {:acronym => "ES", :fullname => "Espírito Santo"}, {:acronym => "GO", :fullname => "Goiás"}, {:acronym => "MA", :fullname => "Maranhão"}, {:acronym => "MT", :fullname => "Mato Grosso"}, {:acronym => "MS", :fullname => "Mato Grosso do Sul"}, {:acronym => "MG", :fullname => "Minas Gerais"}, {:acronym => "PA", :fullname => "Pará"}, {:acronym => "PB", :fullname => "Paraíba"}, {:acronym => "PR", :fullname => "Paraná"}, {:acronym => "PE", :fullname => "Pernambuco"}, {:acronym => "PI", :fullname => "Piauí"}, {:acronym => "RR", :fullname => "Roraima"}, {:acronym => "RO", :fullname => "Rondônia"}, {:acronym => "RJ", :fullname => "Rio de Janeiro"}, {:acronym => "RN", :fullname => "Rio Grande do Norte"}, {:acronym => "RS", :fullname => "Rio Grande do Sul"}, {:acronym => "SC", :fullname => "Santa Catarina"}, {:acronym => "SP", :fullname => "São Paulo"}, {:acronym => "SE", :fullname => "Sergipe"}, {:acronym => "TO", :fullname => "Tocantins"}]
How can I compare a variable with :acronym and return the :fullname in other variable?
I'm trying to do this using a Rails helper.

First of all you don't want to call your array Array as that's a class name and it is already taken.
You could do this:
def find_acronym_in(array, acronym)
# returns nil if we don't find a match.
array.find { |h| h[:acronym] == acronym }.try(:fetch, :fullname)
end
and in your ERB:
<%= find_acronym_in(#acronyms, 'ES') %>
That's a simple linear search so it will be slow for large lists but it probably won't be noticeable for short lists.
If you're doing a lot of this or if you have large lists then you could rearrange your array into a simple Hash in your controller:
#acronyms_hash = #acronyms.each_with_object({ }) { |h, memo| memo[h[:acronym]] = h[:fullname] }
and then just pull things out of the Hash as needed:
<%= #acronyms_hash['ES'] %>

This will do it
acronym_to_find = "SE"
Array.select { |ac| ac[:acronym] == acronym_to_find }.first[:fullname]
Your data would probably be better structured as a hash of { acronym => fullname} pairs, though.

Related

Get Redis Status Through Ruby

I would like to retrieve the Redis status using a Ruby script, I tried the following commands:
redis_status_command, stdeerr, status = Open3.capture3(`redis-cli -h 127.0.0.1 -p 6379 info|grep status`)
OR
redis_status_command, stdeerr, status = Open3.capture3(`systemctl status redis`)
Then when I try to print the variable redis_status_command it returns a blank space, but I know that the commands that are inside the Open3.capture3 part work in the command line. How can I retrieve the Redis status using Ruby? Thank you
With the "redis" gem, you can get all the info properties as follows:
require 'redis'
client = Redis.new(
url: "redis://your-host.your-domain.com",
port: 6379
)
client.info
The output will be a Hash of the info:
{
"redis_version" => "3.2.4",
"redis_git_sha1" => "0",
"redis_git_dirty" => "0",
"redis_build_id" => "0",
"redis_mode" => "standalone",
"os" => "Amazon ElastiCache",
"arch_bits" => "64",
"multiplexing_api" => "epoll",
"gcc_version" => "0.0.0",
"process_id" => "1",
"run_id" => "73f5f76133b7bfd66eb89850a2f9df43e838f567",
"tcp_port" => "6379",
"uptime_in_seconds" => "1754115",
"uptime_in_days" => "20",
"hz" => "10",
"lru_clock" => "5884700",
"executable" => "-",
"config_file" => "-",
"connected_clients" => "10",
"client_longest_output_list" => "0",
"client_biggest_input_buf" => "0",
"blocked_clients" => "0",
"used_memory" => "16110168",
"used_memory_human" => "15.36M",
"used_memory_rss" => "19808256",
"used_memory_rss_human" => "18.89M",
"used_memory_peak" => "19915496",
"used_memory_peak_human" => "18.99M",
"used_memory_lua" => "37888",
"used_memory_lua_human" => "37.00K",
"maxmemory" => "6501171200",
"maxmemory_human" => "6.05G",
"maxmemory_policy" => "volatile-lru",
"mem_fragmentation_ratio" => "1.23",
"mem_allocator" => "jemalloc-4.0.3",
"loading" => "0",
"rdb_changes_since_last_save" => "30264",
"rdb_bgsave_in_progress" => "0",
"rdb_last_save_time" => "1497302809",
"rdb_last_bgsave_status" => "ok",
"rdb_last_bgsave_time_sec" => "-1",
"rdb_current_bgsave_time_sec" => "-1",
"aof_enabled" => "0",
"aof_rewrite_in_progress" => "0",
"aof_rewrite_scheduled" => "0",
"aof_last_rewrite_time_sec" => "-1",
"aof_current_rewrite_time_sec" => "-1",
"aof_last_bgrewrite_status" => "ok",
"aof_last_write_status" => "ok",
"total_connections_received" => "29746",
"total_commands_processed" => "3809776",
"instantaneous_ops_per_sec" => "1",
"total_net_input_bytes" => "382270539",
"total_net_output_bytes" => "3134102675",
"instantaneous_input_kbps" => "0.05",
"instantaneous_output_kbps" => "0.03",
"rejected_connections" => "0",
"sync_full" => "1",
"sync_partial_ok" => "0",
"sync_partial_err" => "0",
"expired_keys" => "0",
"evicted_keys" => "0",
"keyspace_hits" => "674",
"keyspace_misses" => "318",
"pubsub_channels" => "0",
"pubsub_patterns" => "0",
"latest_fork_usec" => "162",
"migrate_cached_sockets" => "0",
"role" => "master",
"connected_slaves" => "1",
"slave0" => "ip=192.168.1.2,port=6379,state=online,offset=341359205,lag=0",
"master_repl_offset" => "341359205",
"repl_backlog_active" => "1",
"repl_backlog_size" => "1048576",
"repl_backlog_first_byte_offset" => "340310630",
"repl_backlog_histlen" => "1048576",
"used_cpu_sys" => "494.00",
"used_cpu_user" => "912.16",
"used_cpu_sys_children" => "0.00",
"used_cpu_user_children" => "0.00",
"cluster_enabled" => "0",
"db0" => "keys=3479,expires=0,avg_ttl=0"
}

Fedex Ruby Gem: Customs Value is required - how to add?

I'm working with the Ruby gem 'FedEx', https://github.com/jazminschroeder/fedex.
I've set up my code for a development mode and I'm testing making a shipment.
However, I get stuck with the following error:
C:/Ruby22/lib/ruby/gems/2.2.0/gems/fedex-.10.1/lib/fedex/request/shipment.rb:134:in 'failure_response': Customs Value is required. (Fedex:: RateError) from C: /Ruby22/lib/ruby/gems/2.2.0/gems/fedex-.10.1/lib/fedex/request/shipment.rb:32:in 'process_request' from C: /Ruby22/lib/ruby/gems/2.2.0/gems/fedex-3.10.1/lib/fedex/shipment.rb:57:in 'ship' from C: /Ruby22/bin/css_fedex_v1.rb:92:in ''
It seems that I need to parse a 'Customs Value', probably as part of my 'packages' hash. However, I'm unable to find the relevant field for me to enter this in. Anyone who's experienced this and found a solution?
My code is as below:
require 'fedex'
fedex = Fedex::Shipment.new(:key => '***',
:password => '***',
:account_number => '***',
:meter => '***',
:mode => 'development')
shipper = { :name => "***",
:company => "***",
:phone_number => "***",
:address => "***",
:city => "***",
:postal_code => "***",
:country_code => "DK" }
recipient = { :name => "***",
:company => "***",
:phone_number => "***",
:address => "***",
:city => "***",
:postal_code => "***",
:country_code => "GB",
:residential => "false" }
packages = []
packages << {:weight => {:units => "LB", :value => 1}}
shipping_options = {:packaging_type => "YOUR_PACKAGING",
:drop_off_type => "REGULAR_PICKUP"}
rate = fedex.rate(:shipper=>shipper,
:recipient => recipient,
:packages => packages,
:shipping_options => shipping_options)
ship = fedex.ship(:shipper=>shipper,
:recipient => recipient,
:packages => packages,
:service_type => "INTERNATIONAL_PRIORITY",
:shipping_options => shipping_options)
puts ship[:completed_shipment_detail][:operational_detail][:transit_time]
Customs value is declared in their docs:
https://github.com/jazminschroeder/fedex/commit/9f1d4c67b829aaa4eeba9090c1a45d3bd507aab3#diff-4f122efb7c0d98120d8b7f0cd00998e4R106
customs_value = { :currency => "USD",
:amount => "200" }
As I understand you can pass it into the commodities hash or keep it separate.

How to count values in a array of hashes

I have an array of hashes
[ {:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},....
{:name => "Will", :type => "none", :product => "oranges"} ]
and was wondering if there is a simple way to count the number of product's and store the count as well as the value in an array or hash.
I want the result to be something like:
#products = [{"apples" => 2, "oranges => 1", ...}]
You can do as
array = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
array.each_with_object(Hash.new(0)) { |h1, h2| h2[h1[:product]] += 1 }
# => {"apples"=>2, "oranges"=>1}
You can use Enumerable#group_by and Enumerable#map
array.group_by{|h| h[:product]}.map{|k,v| [k, v.size]}.to_h
# => {"apples"=>2, "oranges"=>1}
While not exactly what the OP was looking for, this may be helpful to many. If you're just looking for the count of a specific product, you could do this:
array = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
array.count { |h| h[:product] == 'apples' }
# => 2
You could count:
hashes = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
hashes.inject(Hash.new(0)) { |h,o| h[o[:product]] += 1; h }
Or maybe...
hashes.instance_eval { Hash[keys.map { |k| [k,count(k)] }] }
I do not know which is the more performant, the latter seims weird to read though.
I would do:
items =[ {:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"} ]
counts = items.group_by{|x|x[:product]}.map{|x,y|[x,y.count]}
p counts #=> [["apples", 2], ["oranges", 1]]
Then if you need it as a Hash just do:
Hash[counts]

Nested hash iteration: How to iterate a merge over an ( (array of hashes) within a hash )

I'm trying to do as the title says. Here is my code:
school.each { |x| school[:students][x].merge!(semester:"Summer") }
I think I pinpointed the problem to the "[x]" above. If I substitute an array position such as "[2]" it works fine. How can make the iteration work?
If the info above is not enough or you'd like to offer a better solution, please see the details below. Thanks!
The error message I get:
file.rb:31:in []': no implicit conversion of Array into Integer (TypeError)
from file.rb:31:inblock in '
from file.rb:31:in each'
from file.rb:31:in'
The nested hash below before alteration:
school = {
:name => "Happy Funtime School",
:location => "NYC",
:instructors => [
{:name=>"Blake", :subject=>"being awesome" },
{:name=>"Ashley", :subject=>"being better than blake"},
{:name=>"Jeff", :subject=>"karaoke"}
],
:students => [
{:name => "Marissa", :grade => "B"},
{:name=>"Billy", :grade => "F"},
{:name => "Frank", :grade => "A"},
{:name => "Sophie", :grade => "C"}
]
}
I'm trying to append :semester=>"Summer" to each of the last four hashes. Here is what I'm trying to go for:
# ...preceding code is the same. Changed code below...
:students => [
{:name => "Marissa", :grade => "B", :semester => "Summer"},
{:name=>"Billy", :grade => "F", :semester => "Summer"},
{:name => "Frank", :grade => "A", :semester => "Summer"},
{:name => "Sophie", :grade => "C", :semester => "Summer"}
]
}
Just iterate over the students:
school[:students].each { |student| student[:semester] = "Summer" }
Or, using merge:
school[:students].each { |student| student.merge!(semester: "Summer") }
The issue is that when you do array.each {|x| do something}, x actually refers to each element in the array.
For example, in the first iteration of the loop,
x = {:name => "Marissa", :grade => "B"}
So what you are really doing is trying to reference:
school[:student][{:name => "Marissa", :grade => "B"}]
Which will not work
What you could do instead is create a for loop to track the index.
for i in 0 ... school[:student].count
school[:students][i].merge!(semester:"Summer")
end
Edit: Stefan's solution is much better than mine, but I will leave this up to show where you went wrong.
I would do as below using Hash#store :
require 'awesome_print'
school = {
:name => "Happy Funtime School",
:location => "NYC",
:instructors => [
{
:name => "Blake",
:subject => "being awesome"
},
{
:name => "Ashley",
:subject => "being better than blake"
},
{
:name => "Jeff",
:subject => "karaoke"
}
],
:students => [
{
:name => "Marissa",
:grade => "B"
},
{
:name => "Billy",
:grade => "F"
},
{
:name => "Frank",
:grade => "A"
},
{
:name => "Sophie",
:grade => "C"
}
]
}
school[:students].each{|h| h.store(:semester ,"Summer")}
ap school,:index => false,:indent => 10
output
{
:name => "Happy Funtime School",
:location => "NYC",
:instructors => [
{
:name => "Blake",
:subject => "being awesome"
},
{
:name => "Ashley",
:subject => "being better than blake"
},
{
:name => "Jeff",
:subject => "karaoke"
}
],
:students => [
{
:name => "Marissa",
:grade => "B",
:semester => "Summer"
},
{
:name => "Billy",
:grade => "F",
:semester => "Summer"
},
{
:name => "Frank",
:grade => "A",
:semester => "Summer"
},
{
:name => "Sophie",
:grade => "C",
:semester => "Summer"
}
]
}

Convert string into variable within for loop

Given the following code in RUBY, I need to loop through a bunch of hashes. The problem is, varX is a string, I need it to be a variable. Any ideas?
element1_old = {:ip => "192.168.0.191", :state => "PA", :county => "ambler"}
element1_new = {:ip => "192.168.0.191", :state => "PA", :county => "warrington"}
element2_old = {:ip => "192.168.0.192", :state => "PA", :county => "ambler"}
element2_new = {:ip => "192.168.0.192", :state => "PA", :county => "ambler"}
element3_old = {:ip => "192.168.0.200", :state => "PA", :county => "warrington"}
element3_new = {:ip => "192.168.0.200", :state => "PA", :county => "ambler"}
for i in 1..3
var1 = "element#{i}_old"
var2 = "element#{i}_new"
p element"#{i}".not_in_both("element#{i}_old")
end
Throw the hashes into another hash:
h = {
'element1_old' => {:ip => "192.168.0.191", :state => "PA", :county => "ambler"},
'element1_new' => {:ip => "192.168.0.191", :state => "PA", :county => "warrington"},
'element2_old' => {:ip => "192.168.0.192", :state => "PA", :county => "ambler"},
'element2_new' => {:ip => "192.168.0.192", :state => "PA", :county => "ambler"},
'element3_old' => {:ip => "192.168.0.200", :state => "PA", :county => "warrington"},
'element3_new' => {:ip => "192.168.0.200", :state => "PA", :county => "ambler"}
}
for i in 1..3
old = h["element#{i}_old"]
new = h["element#{i}_new"]
p new.not_in_both(old)
end
I'm assuming that element"#{i}" is actually supposed to be element"#{i}"_new in your pseudo-Ruby example and that you have monkey patched not_in_both into Hash.

Resources