How to use has_key with a collection? - ruby-on-rails

I Have an collection:
[a, b, c]
and i want verify if a hash contains some key of this collection
I try:
col = [a, b, c]
my_hash = {c => 1, f => 2, h => 3}
my_hash.has_key? col
=> false
but not work.
Can anybody help me?
Thanks.

1. Iterate over col and check each.
No explanation required.
2. Use existing library functionality to do the same:
keys = [:a, :b, :c]
h = { c: 1, f: 2, h: 3 }
h.any? { |key, val| keys.include? key }
=> true
3. Set math:
h.keys & keys
=> [:c]
Then wrap it up to return true/false depending on which way you want things to read.

Try this:
my_hash.keys & col
# => [c]
& intersects the list of keys with the col array, returning only item in col which appear as keys in my_hash.
Another option - values_at:
my_hash.values_at(*col).compact
# => [1]

But you can do:
my_hash.any? { |key,_| col.include?(key) }
Read it like - Any key from my_hash included in col array.

Related

Using .map function to create hashes

I have an array [5,2,6,4] and I would like to create a structure such as the first minus the second etc until the last row.
I have tried using map, but not sure how to proceed since i might need indxes.
I would like to store the result in something that looks like:
{1 => (5, 2, 3), 2 =>(2,6,-4), 3 => (6,4,2)}
So an array of x should return x-1 hashes.
Anybody knows how to do? should be a simple one.
Thank you.
First, you want to work with the array elements in pairs: 5,2, 2,6, ... That means you want to use each_cons:
a.each_cons(2) { |(e1, e2)| ... }
Then you'll want the index to get the 1, 2, ... hash keys; that suggests throwing a Enumerator#with_index into the mix:
a.each_cons(2).with_index { |(e1, e2), i| ... }
Then you can use with_object to get the final piece (the hash) into play:
a.each_cons(2).with_index.with_object({}) { |((e1, e2), i), h| h[i + 1] = [e1, e2, e1 - e2] }
If you think all the parentheses in the block's arguments are too noisy then you can do it in steps rather than a single one-liner.
You can use each_index:
a = [5, 2, 6, 4]
h = {}
a[0..-2].each_index { |i| h[i+1] = [a[i], a[i+1], a[i] - a[i+1]] }
h
=> {1=>[5, 2, 3], 2=>[2, 6, -4], 3=>[6, 4, 2]}
Try to use
each_with_index
Suppose you have an array:
arr = [3,[2,3],4,5]
And you want to covert with hash(key-value pair). 'Key' denotes an index of an array and 'value' denotes value of an array. Take a blank hash and iterate with each_with_index and pushed into the hash and finally print the hash.
Try this:
hash={}
arr.each_with_index do |val, index|
hash[index]=val
end
p hash
Its output will be:
{0=>3, 1=>[2, 3], 2=>4, 3=>5}
If you want that index always starts with 1 or 2 etc then use
arr.each.with_index(1) do |val, index|
hash[index] = val
end
Output will be:
{1=>3, 2=>[2, 3], 3=>4, 4=>5}

Ruby: get the max occurrences of many hashes depending their content

I usually count the max occurrences of an array of items (int) like this:
specialties_with_frequency = specialties.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
#reference.specialty_id = specialties.max_by { |v| specialties_with_frequency[v] }
Today, I need to count the max occurrences of hashes content.
varietal is a database object containing these fields:
id, grape_id, percent
My duplicate object can have multiple varietals.
#duplicates.each do |duplicate|
duplicate.varietals.each do |varietal|
end
end
For example, browsings duplicates, I will have:
duplicate 1: varietals => {grape_id => 1}, {grape_id => 2}
duplicate 2: varietals => {grape_id => 3}
duplicate 3: varietals => {grape_id => 1}, {grape_id => 2}
duplicate 4: varietals => {grape_id => 3}, {grape_id => 5}
In this case, the accepted data will be:
{grape_id => 1}, {grape_id => 2}
because there are 2 occurrences browsing all duplicates.
I have no idea of how to explore the same values in all occurrences.
Thanks,
Alexandre
You can use the exact same code as before, only with varietals arrays as keys in your frequency hash. Just make sure the arrays are sorted so that the keys will be equal for the same content.
If the grape_id is the only field used for occurence checking, you can simplify a bit by mapping the array of varietals to an array of numbers, in which case your frequency builder will look like this:
specialties_with_frequency = #duplicates.inject(Hash.new(0)) do |h, duplicate|
grape_ids = duplicate.varietals.map { |v| v[:grape_id] }.sort
h[grape_ids] += 1; h
end
Given the example you provided, the value should now be:
{[1, 2]=>2, [3]=>1, [3, 5]=>1}
For arrays and hashes it’s better to use Enumerable#group_by:
with_freq = whatever.group_by { |v| v } # (&:itself) for ruby2.3
.map { |k, v| [k, v.count] }
.to_h
If you need some sophisticated algorithm for grouping, change { |v| v } to use this algorithm.

Get keys of activerecord

I've got an active record to which I want to collect its keys in a seperate array
So if my #item.first has
item.a = 1
item.b = 2
item.c = 3
I want to collect an array like [a => 1, b => 2, c => 3].
Is there a way to do this?
This can be done with attributes:
#item.first.attributes
And to select specific attributes you can filter with select as:
#item.first.attributes.select { |key| ['a', 'b', 'c'].include?(key) }
yes you can do it using as_json read this http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json

Ruby Hash Value into Array of Values

I have a hash {:a => b} and I want to add a value to that key and turn it into an array of values keeping the previous one.
So the result would be {:a => [b, c]}
Is there a better way to do this than iterating through the hash?
Try This.
h = {a: b}
h[:a] = ((a[:a].is_a? Array) ? a[:a] : [a[:a]]) << c
Simple solution would be to create a Hash of Arrays:
h = {}
h[:a] = []
h[:a].push(b)
h[:a].push(c)
What I mean: Even if there's only one value use an array. That makes handling easier.

Ruby mixed array to nested hash

I have a Ruby array whose elements alternate between Strings and Hashes. For example-
["1234", Hash#1, "5678", Hash#2]
I would like to create a nested hash structure from this. So,
hash["1234"]["key in hash#1"] = value
hash["5678"]["key in hash#2"] = value
Does anyone have/now a nice way of doing this? Thank you.
Simply use
hsh = Hash[*arr] #suppose arr is the array you have
It will slice 2 at a time and convert into hash.
I don't think there is a method on array to do this directly. The following code works and is quite easy to read.
hsh = {}
ary.each_slice(2) do |a, b|
hsh[a] = b
end
# Now `hsh` is as you want it to be
Guessing at what you want, since "key in hash#1" is not clear at all, nor have you defined what hash or value should be:
value = 42
h1 = {a:1}
h2 = {b:2}
a = ["1234",h1,"5678",h2]
a.each_slice(2).each{ |str,h| h[str] = value }
p h1, #=> {:a=>1, "1234"=>42}
h2 #=> {:b=>2, "5678"=>42}
Alternatively, perhaps you mean this:
h1 = {a:1}
h2 = {b:2}
a = ["1234",h1,"5678",h2]
hash = Hash[ a.each_slice(2).to_a ]
p hash #=> {"1234"=>{:a=>1}, "5678"=>{:b=>2}}
p hash["1234"][:a] #=> 1
let's guess, using facets just for fun:
require 'facets'
xs = ["1234", {:a => 1, :b => 2}, "5678", {:c => 3}]
xs.each_slice(2).mash.to_h
#=> {"1234"=>{:a=>1, :b=>2}, "5678"=>{:c=>3}}

Resources