Append the value to duplicate hash - ruby-on-rails

Hello I wanted to create a hash that would be append the email with name if that name exist in someother hash. I believe there would be small piece of code that will do the ruby magic.
Input
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam"}
]
Output
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam | foobar#gmail.com"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam | hello#gmail.com "}
]

Here's another option:
# get names
names = a.map {|e| e['name'] }
# find duplicates
duplicates = names.detect {|e| names.count(e) > 1 }
# append email to duplicates
a.each { |e| e['name'] = "#{e['name']} | #{e['email']}" if duplicate.include?(e['name'])}

Given your input
a = [
{"email"=>"foobar#gmail.com", "name"=>"Adam"},
{"email"=>"test#gmail.com", "name"=>"John"},
{"email"=>"hello#gmail.com", "name"=>"Adam"}
]
And I'll provide a cleverly named comparison hash of my own
b = [
{"name"=>"Adam"},
{"name"=>"Adam"}
]
Here's your ruby magic
a.map do |hash_a|
# This is the 'magic' line that compares the values of
# the two hashes name values
if b.any? { |hash_b| hash_b['name'] == hash_a['name'] }
hash_a['name'] << " | #{hash_a['email']}"
hash_a
else
hash_a
end
end
Output:
[
{
"email" => "foobar#gmail.com",
"name" => "Adam | foobar#gmail.com"
},
{
"email" => "test#gmail.com",
"name" => "John"
},
{
"email" => "hello#gmail.com",
"name" => "Adam | hello#gmail.com"
}
]

Related

RUBY - Correct way of doing array of hashes inside of hash

i need to do an array of hashes inside of a hash, something like this:
merit_hash => {
students => [
{
"id": id,
"name": name,
subjects => [
{
"id": id,
"grade": grade
},
{
"id": id,
"grade": grade
}
]
},
{
"id": id,
"name": name,
subjects => [
{
"id": id,
"grade": grade
},
{
"id": id,
"grade": grade
}
]
}
]
}
Right now, i just have the array of student hashes, but i dont exactly know how to put the subject array inside of it, im doing this:
merit = {}
merit["students"] = []
students.each do |students|
student_subjects = Array.new
merit["students"].push(
{
"id" => students.id,
"name" => students.name.to_s
selected_batch_subjects.each do |subjects|
grade = FinalGrades.where(batch_subject_id:subjects.id, period_id: period.id, student_id: student.id).first.value
student_subjects.push(
{
"id" => subjects.id,
"grade"=> grade
}
)
end
}
)
end
but throws this error
unexpected '}', expecting keyword_end
when i try to close the student hash... what can i do to make this work? or, whats the best way of implementing this?
Thanks!
Something like this should work:
merit = {}
merit["students"] = []
students.each do |student|
student_information = {"id" => student.id, "name" => student.name.to_s}
student_subjects = []
selected_batch_subjects.each do |subjects|
grade = FinalGrades.where(batch_subject_id:subjects.id, period_id: period.id, student_id: student.id).first.value
student_subjects.push({"id" => subjects.id, "grade" => grade})
end
student_information[:subjects] = student_subjects
merit["students"].push(student_information)
end
The important part is adding each student's subjects to the already existing hash.
Your iterations are not very clear to me but for current loop and array push you could do like this:
merit = {}
merit["students"] = []
students.each do |students|
student_subjects = []
merit["students"] << {
"id" => students.id,
"name" => students.name.to_s
}
selected_batch_subjects.each do |subjects|
grade = FinalGrades.where(batch_subject_id:subjects.id, period_id: period.id, student_id: student.id).first.value
student_subjects << {"id" => subjects.id,"grade"=> grade}
end
end

how do I search for a string value inside an array stored in a hash

I am using ruby on rails and trying to figure out if I can (and/or how I) search for a Hash within an Array for a specific string value? If there is a match (finds Bob), I want it to return True.
```
string_query = "Bob#gmail.com"
email_array is the following:
[
[0] {
"email" => "bill#gmail.com",
"name" => "william"
},
[1] {
"email" => "mike#gmail.com",
"name" => "michael"
},
[2] {
"email" => "Bob#gmail.com",
"name" => "robert"
}
]
```
I see this example on Stack Overflow - but it is numeric. Mine is a string.
How do I get a hash from an array based on a value in the hash?
Many thanks.
I have not tried this as I am out now, but this could work
string_query = "Bob#gmail.com"
email_array.each do |s|
if s['email'] == string_query
#your comparision statements here
end
end
string_query = "Bob#gmail.com"
email_array = [{
"email" => "bill#gmail.com",
"name" => "william"
},
{
"email" => "mike#gmail.com",
"name" => "michael"
},
{
"email" => "Bob#gmail.com",
"name" => "robert"
},
{
"email" => "Bob#gmail.com",
"name" => "robert2"
}
]
If you want to select all of the matching hashes you can use select
email_array.select {|hash| hash["email"] == string_query }
#=> [{"email"=>"Bob#gmail.com", "name"=>"robert"}, {"email"=>"Bob#gmail.com", "name"=>"robert2"}]
If you simply want to check for true or false, use any?
email_array.any? {|hash| hash["email"] == string_query }
#=> true
If you are only interested in the first instance. You can use detect
email_array.detect {|hash| hash["email"] == string_query }
#=> {"email"=>"Bob#gmail.com", "name"=>"robert"}
You could do this
email_array.select {|hash| hash["email"] == string_query }.present?

Escape '#' in names

I use Rails 4.2.0 with ActiveResource to implement a webclient for server API.
The problem I've faced is that server resources contains '#' and '##' in attribute names. So these attributes can't be processed correctly by ActiveResource while creating ARes object.
Example: server returns JSON data:
{"##artist"=>
{"#id"=>"some_text_id",
"#name"=>"Carman",
"#publisher"=>"Carmen radio",
"#category"=>"Music",
"#automaticallyGenerated"=>true,
"##options"=>{"#public"=>true, "#enabled"=>false},
"_extended"=>{"#container"=>"Music box", "region"=>"Europe"}}}
The variant to rename attributes before ARes object is created: (remove '#' from name or replace it for another symbol). In that case I need to do back rename attributes before send POST, PUT requests (call resource.save for example) E.g. add '#' or '##' in the beginning of the names.
Could you suggest more flexible and pretty variant?
I rly dont know what ist your output, but you can use something like this.
This is just example.
input = {
"##artist"=>
{"#id"=>"some_text_id",
"#name"=>"Carman",
"#publisher"=>"Carmen radio",
"#category"=>"Music",
"#automaticallyGenerated"=>true,
"##options"=>{"#public"=>true, "#enabled"=>false},
"_extended"=>{"#container"=>"Music box", "region"=>"Europe"}
}
}
def transcode(hash)
result = {}
hash.each do |k, v|
result[k.gsub(/#*/, "")] = ( Hash === v ? transcode(v) : v )
end
result
end
output = transcode(input)
#{
# "artist" => {
# "id" => "some_text_id",
# "name" => "Carman",
# "publisher" => "Carmen radio",
# "category" => "Music",
# "automaticallyGenerated" => true,
# "options" => {
# "public" => true,
# "enabled" => false
# },
# "_extended" => {
# "container" => "Music box",
# "region" => "Europe"
# }
# }
#}
BACK
input = {
"##artist"=>
{"#id"=>"some_text_id",
"#name"=>"Carman",
"#publisher"=>"Carmen radio",
"#category"=>"Music",
"#automaticallyGenerated"=>true,
"##options"=>{"#public"=>true, "#enabled"=>false},
"_extended"=>{"#container"=>"Music box", "region"=>"Europe"}
}
}
def transcode(hash)
result = {}
hash.each do |k, v|
result[k.gsub(/#*/, "")] = ( Hash === v ? transcode(v) : v )
end
result
end
def transcode_back(hash, output)
result = {}
hash.each do |k, v|
value = output[k.gsub(/#*/, "")]
result[k] = ( Hash === value ? transcode_back(v, value) : value )
end
result
end
output = transcode(input)
# you can modify values
#output["artist"]["name"] = "CarmanNew"
result = transcode_back(input, output)
output == result # is same ?
# true

Search a table for two matching values using a hash in Ruby on Rails

I have the following hash
{ "1" => "a", "2" => "a", "3" => "2"}
and the following sqlite3 table named ITEMS:
POSITION CODE NAME VALUE
"1" "a" "Cat" "Small"
"1" "b" "Cat" "Big"
"2" "a" "Fish" "Red"
"2" "b" "Fish" "Blue"
"3" "1" "Car" "Fast"
"3" "2" "Car" "Slow"
I would like to query the table and return a hash of format {"NAME" => "VALUE"}.
The input hash is in the format {"POSITION" => "CODE"}, so the first value in the hash above has position "1" with code "a", which would return Name "Cat" and Value "Small". The real version of this will have an initial hash of 20 values, and a table with closer to 200 records.
The example hash above should return:
{ "Cat" => "Small", "Fish" => "Red", "Car" => "Slow" }
Here is some code :
Item.where("(POSITION = ? AND CODE = ?) OR
(POSITION = ? AND CODE = ?) OR
(POSITION = ? AND CODE = ?)", *hash.flatten
)
.select("name, value")
.map { |rec| [rec.name, rec.value] }.to_h
update
As #mudasobwa said
Item.where((["(POSITION = ? AND CODE = ?)"] * hash.size).join(' OR '), hash.flatten)
.select("name, value")
.map { |rec| [rec.name, rec.value] }.to_h
This is a wonderful tip. I liked it too much.

How to "trasform" an array of hash so that you can customize logic to access its data?

I am using Ruby on Rails 3 and I would like to "trasform" the following array so that I can use my custom logic to access its data.
This is the original array from which I have to build a new one
[
{
"account" => {
"id" => 45,
"name" => "Test_name",
"..." => ..."
}
},
{
"other" => {
"sub_other" => {...}
}
}
]
I would like to trasform the above array so that I can do in my controller something like
array_name[45]
# => {
"name" => "Test_name",
"..." => ..."
}
but only for the account hashs. The other hash should remain untouched.
How can I proceed to build the new array?
If I understand your requirements correctly, I think you are better off constructing a hash from account id to account data. Perhaps something like this will work:
arr = [
{
"account" => {
"id" => 45,
"name" => "Test_name",
"..." => "..."
}
},
{
"other" => {
"sub_other" => "..."
}
}
]
account_hashes = arr.select {|item| item.keys.first == "account"}
answer = account_hashes.inject({}) do |acc, item|
acc[item["account"].delete("id")] = item["account"]
acc
end

Resources