How do I select an anonymous hash within an array? - ruby

I have the following array where I want to select each of the keys:
names = [
{"Ánias"=>{:gender=>"male", :nationality=>"faroese"}},
{"Annfinnur"=>{:gender=>"male", :nationality=>"faroese"}},
{"Ansgar"=>{:gender=>"male", :nationality=>"faroese"}}
]
How would I go about selecting all the names ("Ánias", "Annfinnur", "Ansgar")?

Just do
names = [
{"Ánias"=>{:gender=>"male", :nationality=>"faroese"}},
{"Annfinnur"=>{:gender=>"male", :nationality=>"faroese"}},
{"Ansgar"=>{:gender=>"male", :nationality=>"faroese"}}
]
names.map { |h| h.keys.first }
# => ["Ánias", "Annfinnur", "Ansgar"]

Related

Merge duplicated values in array of hashes

I have an array of hashes like this
arr_of_hashes = [
{"started_at"=>"2018-07-11", "stopped_at"=>"2018-07-11"},
{"started_at"=>"2018-07-13", "stopped_at"=>"2018-07-13"},
{"started_at"=>"2018-07-13", "stopped_at"=>"2018-07-13"},
{"started_at"=>"2018-07-16", "stopped_at"=>"2018-07-16"},
{"started_at"=>"2018-07-16", "stopped_at"=>"2018-07-16"},
{"started_at"=>"2018-07-16", "stopped_at"=>"still active"}
]
I want to remove duplicates. Also, among:
{"started_at"=>"2018-07-16", "stopped_at"=>"2018-07-16"},
{"started_at"=>"2018-07-16", "stopped_at"=>"still active"}
I want to keep only the last line. How can I do that?
I tried to do:
sorted_arr = arr_of_hashes.uniq
arr_of_hashes.reverse.uniq { |hash| hash["started_at"] }.reverse
About pass block to uniq and about reverse.
#result
[
{"started_at"=>"2018-07-11", "stopped_at"=>"2018-07-11"},
{"started_at"=>"2018-07-13", "stopped_at"=>"2018-07-13"},
{"started_at"=>"2018-07-16", "stopped_at"=>"still active"}
]
Something like this?
[2] pry(main)> arr_of_hashes.reject { |h| h['started_at'] == h['stopped_at'] }
[
[0] {
"started_at" => "2018-07-16",
"stopped_at" => "still active"
}
]
Its not clear form your question what output you want to get
arr_of_hashes.each_with_object({}) { |g,h| h.update(g["started_at"]=>g) }.values
#=> [{"started_at"=>"2018-07-11", "stopped_at"=>"2018-07-11"},
# {"started_at"=>"2018-07-13", "stopped_at"=>"2018-07-13"},
# {"started_at"=>"2018-07-16", "stopped_at"=>"still active"}]
See Hash#update (a.k.a. merge!) and note that values's receiver is as follows.
arr_of_hashes.each_with_object({}) { |g,h| h.update(g["started_at"]=>g) }
#=> {"2018-07-11"=>{"started_at"=>"2018-07-11", "stopped_at"=>"2018-07-11"},
# "2018-07-13"=>{"started_at"=>"2018-07-13", "stopped_at"=>"2018-07-13"},
# "2018-07-16"=>{"started_at"=>"2018-07-16", "stopped_at"=>"still active"}}

Including empty k/v pairs when merging hashes

There are three hashes. Each hash results in a single key/value pair.
When merged and outputted to a json file, the only k/v pairs visible are the ones with data.
For example:
employee_hours[ name ] = {"Hours" => hours}
employee_revenue [ name ] = {"Revenue" => revenue}
employee_activations [ name ] = {"Activations" => activations}
If any of the k/v pairs don't exist I need them to be included in the output with a value of 0.00.
I tried to simply just include empty k/v pairs from the other hashes in each hashtable, but when merged, they overwrite existed values.
employee_hours[ name ] = {"Hours" => hours, "Revenue" = "", Activations = ""}
employee_revenue [ name ] = {"Hours" => "", "Revenue" => revenue, Activations = ""}
employee_activations [ name ] = {"Hours" => "", "Revenue" => "", "Activations" => activations}
Edit
My current code is listed here: https://gist.github.com/hnanon/766a0d6b2b0f9d9d03fd
You need to define a hash for the default values and merge into it. Assuming that employee_final is the hash where you merged all the employee information,
employee_defaults = { "Hours" => 0.0, "Revenue" => 0.0 }
employee_final.each_key do |name|
employee_final[name] = employee_defaults.merge(employee_final[name])
end
It sounds as if you need to define a 'REQUIRED_KEYS' array, and add check on their existence in your hashes. Here's one way to achieve that:
REQUIRED_KEYS = [ "A", "B", "C" ]
DEFAULT_VALUE = 0.0
REQUIRED_KEYS.each { |key| your_hash[key] = DEFAULT_VALUE if not your_hash.has_key?(key) }
Use Hash Defaults
You can use an argument to Hash#new to set a default value for a hash. For example:
require 'json'
employee_hours = Hash.new(0.0)
employee_revenue = Hash.new(0.0)
employee_activations = Hash.new(0.0)
name = 'Bob'
{
'Hours' => employee_hours[name],
'Revenue' => employee_revenue[name],
'Activations' => employee_activations[name],
}.to_json
# => "{\"Hours\":0.0,\"Revenue\":0.0,\"Activations\":0.0}"

What is an eloquent way to sort an array of hashes based on whether a key is empty in Ruby?

array = [{ name:'Joe', foo:'bar' },
{ name:'Bob', foo:'' },
{ name:'Hal', foo:'baz' }
]
What is an eloquent way to sort so that if foo is empty, then put it at the end, and not change the order of the other elements?
Ruby 1.9.3
array.partition { |h| !h[:foo].empty? }.flatten
array.find_all{|elem| !elem[:foo].empty?} + array.find_all{|elem| elem[:foo].empty?}
returns
[{:name=>"Joe", :foo=>"bar"}, {:name=>"Hal", :foo=>"baz"}, {:name=>"Bob", :foo=>""}]
array = [
{ name:'Joe', foo:'bar' },
{ name:'Bob', foo:'' },
{ name:'Hal', foo:'baz' }
]
arraydup = array.dup
array.delete_if{ |h| h[:foo].empty? }
array += (arraydup - array)
Which results in:
[
[0] {
:name => "Joe",
:foo => "bar"
},
[1] {
:name => "Hal",
:foo => "baz"
},
[2] {
:name => "Bob",
:foo => ""
}
]
With a little refactoring:
array += ((array.dup) - array.delete_if{ |h| h[:foo].empty? })
One can produce keys as tuples, where the first part indicates null/not-null, and the second part is the original index, then sort_by [nulls_last, original_index].
def sort_nulls_last_preserving_original_order array
array.map.with_index.
sort_by { |h,i| [ (h[:foo].empty? ? 1 : 0), i ] }.
map(&:first)
end
Note this avoids all the gross array mutation of some of the other answers and is constructed from pure functional transforms.
array.each_with_index do |item, index|
array << (array.delete_at(index)) if item[:foo].blank?
end
Use whatever you have in place of blank?.

Ruby easy search for key-value pair in an array of hashes

Suppose I have this array of hashes:
[
{"href"=>"https://company.campfirenow.com", "name"=>"Company", "id"=>123456789, "product"=>"campfire"},
{"href"=>"https://basecamp.com/123456789/api/v1", "name"=>"Company", "id"=>123456789, "product"=>"bcx"},
{"href"=>"https://company.highrisehq.com", "name"=>"Company", "id"=>123456789, "product"=>"highrise"}
]
How can I parse the "href" value of the hash where "product"=>"bcx"
Is there any easy way to do this in Ruby?
ary = [
{"href"=>"https://company.campfirenow.com", "name"=>"Company", "id"=>123456789, "product"=>"campfire"},
{"href"=>"https://basecamp.com/123456789/api/v1", "name"=>"Company", "id"=>123456789, "product"=>"bcx"},
{"href"=>"https://company.highrisehq.com", "name"=>"Company", "id"=>123456789, "product"=>"highrise"}
]
p ary.find { |h| h['product'] == 'bcx' }['href']
# => "https://basecamp.com/123456789/api/v1"
Note that this only works if the element exists. Otherwise you will be calling the subscription operator [] on nil, which will raise an exception, so you might want to check for that first:
if h = ary.find { |h| h['product'] == 'bcx' }
p h['href']
else
puts 'Not found!'
end
If you need to perform that operation multiple times, you should build yourself a data structure for faster lookup:
href_by_product = Hash[ary.map { |h| h.values_at('product', 'href') }]
p href_by_product['campfire'] # => "https://company.campfirenow.com"
p href_by_product['bcx'] # => "https://basecamp.com/123456789/api/v1"

Ruby: select a hash from inside an array

I have the following array:
response = [{"label"=>"cat", "name"=>"kitty", "id"=>189955}, {"label" => "dog", "name"=>"rex", "id" => 550081}]
How do I select the hash that contains the label cat? I know response.first will give me the same result, but I want to search the by label.
Thanks!
Deb
response.find {|x| x['label'] == 'cat' } #=> {"label"=>"cat", "name"=>"kitty", "id"=>189955}
Try:
response.select { |x| x["label"] == "cat" }

Resources