Separate subhash from hash [closed] - ruby

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have the following hash_of_student_and_grades.
{132=>{"Design"=>6, "English"=>5, "Humanities"=>5, "Languages"=>6, "Math"=>6, "Music"=>7,
"PE"=>6, "Science"=>6, "Theatre"=>6},
134=>{"Design"=>7, "English"=>6, "Humanities"=>6, "Languages"=>6, "Math"=>5, "Music"=>6,
"PE"=>6, "Science"=>7, "Art"=>6},
136=>{"Design"=>5, "English"=>4, "Humanities"=>5, "Languages"=>6, "Math"=>6, "Music"=>6,
"PE"=>7, "Science"=>5, "Theatre"=>6},...}
Now I want to make hash with key like this.
id132={"Design"=>6, "English"=>5, "Humanities"=>5, "Languages"=>6, "Math"=>6, "Music"=>7,
"PE"=>6, "Science"=>6, "Theatre"=>6}
id134={"Design"=>7, "English"=>6, "Humanities"=>6, "Languages"=>6, "Math"=>5, "Music"=>6,
"PE"=>6, "Science"=>7, "Art"=>6}
...
...
UPDATE:
I have done this so far. But it does not assign each hash to key.
resulthash.each {|key, value| puts key=value}
# outputs
{"Design"=>6, "English"=>5, "Humanities"=>5, "Languages"=>6, "Math"=>6, "Music"=>7, "PE"=>6, "Science"=>6, "Theatre"=>6}
{"Design"=>7, "English"=>6, "Humanities"=>6, "Languages"=>6, "Math"=>5, "Music"=>6, "PE"=>6, "Science"=>7, "Theatre"=>6}
How can I accomplish this?

You can't use digits as variable names, but if it would be id132, id133 etc you can accomplish this using metaprogramming and instance variables:
hash = {"i1"=>{"a"=>"b"}, "i2"=>{"c"=>"d"}}
hash.each { |key, value| instance_variable_set("##{ key }", value) }
puts #i1 # => {"a"=>"b"}

Because you can(ruby gives you ability to shoot your foot),here is answer:
In ruby id32 is the name of variable.
Hash's key can be any type: number, string... object.
Basic types(number, string, nil, false, true) are evaluated like this:
n1 = 2
n2 = 2
h = {2 => 42}
h[n1] # 42
h[n2] # 42
In other words you get/set hash's key 2 not n1 or n2. It would be hard to change basic types.
Objects, on other hands, you can modify:
class N
def initialize name
#name=name #contains name, like `id32`, `id34`
end
def to_s #this method let you show any text, here name(for example `id32`)
"#{#name}"
end
end
id32 = N.new 'id32'
h={id32 => 42}
#{id32=>42}
#adding more keys/values
id34 = N.new 'id34'
h[id34] = 'some value'
and... that's just basics.
what lots of rubist do:
They use symbols.
What are symbols?
It's type like string but there can be only one symbol!
puts :a.object_id
puts :a.object_id
puts :a.object_id
Code above prints 3 the same numbers because :a is only 1.
puts 'a'.object_id
puts 'a'.object_id
Strings are not the same.
Construction:
You prepend characters with ::
`:a`
or if it has weird character, prepend with : and surround with ' or ":
:'a'
To sum up:
Your code will look exactly the same, will be faster(no need for objects like above):
h ={:a => :b}
or from 1.9.x(i don't remember correct number) you can use this syntax too:
h = {a: :b}

Related

How to filter the payload response in ruby by converting key and value pair [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Below is a payload response as a string assigned to string, and it needs to be converted into a hash.
{"method_name":"My function","success":true,"payload":[{"Type":"SM::Mod::Elu","Properties":{"TVset":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::VirtualArea","Properties":{"vad_val":{"Type":"String","Mutable":false,"Value":"0001"},"enabled":{"Type":"TrueClass","Mutable":false,"Value":true}},"Children":{"Music":{"Type":"SM::Mod::Base","Properties":{"reg_id":{"Type":"Fixnum","Mutable":true,"Value":null},"buffer_value":{"Type":"Fixnum","Mutable":true,"Value":10},"special_handling_table":{"Type":"SM::Mod::SpecialHandlingTable","Properties":{"behaviors_val":{"Type":"Hash","Mutable":false,"Value":{"1":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Replace","Properties":{"direct":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}},{"Type":"SM::Mod::Behavior","Properties":{"direct_val":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"2":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSH","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"3":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"4":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderres","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"ToTransport"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"5":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Tosnmp"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"6":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSHBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromconn"}},"Children":{}}],"IsActiveChange":null},"7":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"8":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"9":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null}},"IsActiveChange":null}},"Children":{}}},"Children":{}}}}],"IsActiveChange":null},"number":{"Type":"Fixnum","Mutable":false,"Value":0,"IsActiveChange":false},"connections":{"Type":"Fixnum","Mutable":true,"Value":null},"threads":{"Type":"Fixnum","Mutable":true,"Value":4},"updates":{"Type":"TrueClass","Mutable":true,"Value":null},"severity":{"Type":"Fixnum","Mutable":true,"Value":3},"levelval":{"Type":"Fixnum","Mutable":true,"Value":3},"facility":{"Type":"Fixnum","Mutable":true,"Value":3},"trace":{"Type":"smode::Depval::Fallback","Properties":{"enabled":{"Type":"TrueClass","Mutable":true,"Value":false},"depend":{"Type":"String","Mutable":false,"Value":""}},"Children":{}}},"Children":{}}],"error":""}
I need to create key and value pairs by parsing:
vad_val => "001" , enabled => true , req_id => NULL, buffer_value =>10
etc. until end. I need to capture all elements of string, fixnum, and TrueClass as a hash with key and value pair.
I can understand that below code:
parsed = JSON.parse(string) # it returns a hash
p parsed["properties"]["someKey"]=value
can convert the string into a hash, but I am not sure how this kind of filtering can be done. It needs to proceed further through JSON to retrieve the hash, but it will store all other unwanted information. How can I perform filtering to get somekey as a key (vad_val) and value (0001) and etc? I will appreciate your help regarding this.
As I understand it, you want to iterate through the JSON that's created from the raw data and for each nested (key / hash) where the hash has a "Type" key of "String", "TrueClass", or "Fixnum" you want to produce an output key / value consisting of the key and the value of the "Value" key in the hash.
This should do that. It recursively examines all sub-hashes and arrays in the original JSON structure looking for the above match.
raw_data = '{"method_name":"My function","success":true,"payload":[{"Type":"SM::Mod::Elu","Properties":{"TVset":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::VirtualArea","Properties":{"vad_val":{"Type":"String","Mutable":false,"Value":"0001"},"enabled":{"Type":"TrueClass","Mutable":false,"Value":true}},"Children":{"Music":{"Type":"SM::Mod::Base","Properties":{"reg_id":{"Type":"Fixnum","Mutable":true,"Value":null},"buffer_value":{"Type":"Fixnum","Mutable":true,"Value":10},"special_handling_table":{"Type":"SM::Mod::SpecialHandlingTable","Properties":{"behaviors_val":{"Type":"Hash","Mutable":false,"Value":{"1":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Replace","Properties":{"direct":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}},{"Type":"SM::Mod::Behavior","Properties":{"direct_val":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"2":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSH","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"3":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"4":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderres","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"ToTransport"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"5":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Tosnmp"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"6":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSHBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromconn"}},"Children":{}}],"IsActiveChange":null},"7":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"8":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"9":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null}},"IsActiveChange":null}},"Children":{}}},"Children":{}}}}],"IsActiveChange":null},"number":{"Type":"Fixnum","Mutable":false,"Value":0,"IsActiveChange":false},"connections":{"Type":"Fixnum","Mutable":true,"Value":null},"threads":{"Type":"Fixnum","Mutable":true,"Value":4},"updates":{"Type":"TrueClass","Mutable":true,"Value":null},"severity":{"Type":"Fixnum","Mutable":true,"Value":3},"levelval":{"Type":"Fixnum","Mutable":true,"Value":3},"facility":{"Type":"Fixnum","Mutable":true,"Value":3},"trace":{"Type":"smode::Depval::Fallback","Properties":{"enabled":{"Type":"TrueClass","Mutable":true,"Value":false},"depend":{"Type":"String","Mutable":false,"Value":""}},"Children":{}}},"Children":{}}],"error":""}'
require 'json'
def breakdown(set, result = {})
if set.class == Hash # iterate through hash
set.each do |k, v|
if v.class == Hash && %w(String TrueClass Fixnum).include?((v["Type"] || ''))
result[k.to_sym] = v["Value"] # add this key's value to the output array
elsif v.class == Hash || v.class == Array
result = breakdown(v, result) # check nested arrays and hashes
end
end
elsif set.class == Array
set.each do |a|
result = breakdown(a, result) # check elements of an array
end
end
result
end
broken_down = breakdown(JSON.parse(raw_data))
p broken_down
#> {:vad_val =>"0001", :enabled =>false, :reg_id =>nil, :buffer_value =>10, :direct =>"From", :direct_val =>"From", :decision =>"From", :number =>0, :connections =>nil, :threads =>4, :updates =>nil, :severity =>3, :levelval =>3, :facility =>3, :depend =>""}
EDIT
Modified the above to ensure that keys are symbols instead of strings (to match required output)
I don't completely understand what you are wanting the end value to look like. But you will iterate over the hash to generate whatever values you want.
filtered_parsed = parsed.select {|k,v| v.is_a? String}
That would select only the elements where the value is a string. Hope that gets you in the right direction. Check out Enumerable in ruby library for more options.

Checking if content of an array is all integers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm working on a sorting code. I would like to check if my array contains non integers. Here is my code:
array = Array.new
puts "Please enter your 3 digits."
3.times do
str = gets.chomp.to_i
array.push str.to_i
end
if array.is_a?(Numeric) == false
puts "Error, only use Integers please!"
else
print "Here are your sorted numbers: #{array.sort}"
end
You clearly can't gets.chomp.to_i (or the equivalent, gets.to_i), because that will only return integers. You therefore need to see if the string represents a number before adding it to the array.
You can do that with a regular expression or confirm that Kernel::Integer does not raise an exception (and catch it if it does).
A regular expression that would work is simply:
str =~ /^-?\d+$/
after
str = gets.chomp.strip
To use Kernel::Integer:
def integer?(str)
begin
Integer(str)
rescue ArgumentError
return false
end
str.to_i
end
For example,
integer?("-33") #=> -33
integer?("-x33") #=> false
integer?(" 33 ") #=> 33
integer?("33\n") #=> 33
The last two examples show that you can drop chomp.strip from gets.chomp.strip when using this approach.
If you wish to allow integers or floats, change the regular expression to:
/^-?\d+\.?\d*$/
or check to see that Kernel::Float raises an exception:
def float?(str)
begin
Float(str)
rescue ArgumentError
return false
end
str.to_f
end
float?("-33.4") #=> -33.4
float?("-33") #=> -33.0
float?("x33.4") #=> false
float?(" 33.4\n") #=> 33.4
With the code you have above your array is guaranteed to contain integers since you are converting your input to Integers using to_i:
array.push str.to_i
You are in fact doing it twice. When you read the string from STDIN and when you push it onto the array.
You need to check to see if the input is a string before you call to_i.
3.times do
str = gets.chomp
# code to verify if str is numeric.
array.push str
end
There are lots of ways to implement that code depending on what your requirements are. Integers only could be done like this:
unless str =~ /^\d+$/
puts "Error, only use Integers please!"
exit
end
The above would work for any positive integers, but not negative. It would also fail if you allowed decimals. But it gives you an idea. Search "ruby check if string is a number" and you'll find a lot more info.
Also note that the above fails as soon as it finds a non integer instead of waiting till after.

What is the correct way to use variable symbols in a hash? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have two arrays:
people_keys = ['id', 'name', 'email']
people_values = [[1, 'Tarzan', 'tarzan#jungle.com'],
[2, 'Jane', 'jane#jungle.com' ]]
and I want to make an array of people:
people = []
people_values.each do |person_values|
person = {}
person_values.each_with_index do |person_value, index|
person[people_keys[index]] = person_value
end
people.push( person )
end
This gives me the following result:
people # => [{"id"=>1, "name"=>"Tarzan", "email"=>"tarzan#jungle.com"},
# {"id"=>2, "name"=>"Jane", "email"=>"jane#jungle.com" }]
I want to make id, name and email symbols instead of strings,
so I came up with the following:
I replaced
person[people_keys[index]] = person_value
with
person[:"#{people_keys[index]}"] = person_value
This gives me the following result:
people # => [{:id=>1, :name=>"Tarzan", :email=>"tarzan#jungle.com"},
# {:id=>2, :name=>"Jane", :email=>"jane#jungle.com" }]
This works just fine but seems like it could be done better/cleaner,
but I am unable to find a better solution.
I'd like to know if there is in fact a better solution for this problem.
Ruby's String class has a to_sym method:
Returns the Symbol corresponding to str, creating the symbol if it did not previously exist.
You could do something like this:
people_values.map { |person| people_keys.map(&:to_sym).zip(person).to_h }

Learn Ruby the Hard Way #41 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Hi I`m learning from LRtHW and I got stuck....
I have program like this:
require 'open-uri'
WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []
PHRASES = {
"class ### < ###\nend" => "Make a class named ### that is-a ###.",
"class ###\n\tdef initialize(###)\n\tend\nend" => "class ### has-a initialize that takes ### parameters.",
"class ###\n\tdef ***(###)\n\tend\nend" =>"class ### has-a function named *** that takes ### parameters.",
"*** = ###.new()" => "Set *** to an instance of class ###.",
"***.***(###)" => "From *** get the *** function, and call it with parameters ###.",
"***.*** = '***'" => "From *** get the *** attribute and set it to '***'."
}
PHRASE_FIRST = ARGV[0] == "english"
open(WORD_URL) do |f|
f.each_line {|word| WORDS.push(word.chomp)}
end
def craft_names(rand_words, snippet, pattern, caps=false)
names = snippet.scan(pattern).map do
word = rand_words.pop()
caps ? word.capitalize : word
end
return names * 2
end
def craft_params(rand_words,snippet,pattern)
names = (0...snippet.scan(pattern).length).map do
param_count = rand(3) + 1
params = (0...param_count).map {|x| rand_words.pop()}
params.join(', ')
end
return names * 2
end
def convert(snippet, phrase)
rand_words = WORDS.sort_by {rand}
class_names = craft_names(rand_words, snippet, /###/, caps=true)
other_names = craft_names(rand_words, snippet,/\*\*\*/)
param_names = craft_params(rand_words, snippet, /###/)
results = []
for sentence in [snippet, phrase]
#fake class name, also copies sentence
result = sentence.gsub(/###/) {|x| class_names.pop}
#fake other names
result.gsub!(/\*\*\*/) {|x| other_names.pop}
#fake parameter list
result.gsub!(/###/) {|x| param_names.pop}
results.push(result)
end
return results
end
# keep going until they hit CTRL-D
loop do
snippets = PHRASES.keys().sort_by { rand }
for snippet in snippets
phrase = PHRASES[snippet]
question, answer = convert(snippet, phrase)
if PHRASE_FIRST
question, answer = answer, question
end
print question, "\n\n> "
odp = gets.chomp
if odp == "exit"
exit(0)
end
#exit(0) unless STDIN.gets
puts "\nANSWER: %s\n\n" % answer
end
end
I understand most of this code, but I have a problem with:
for sentence in [snippet, phrase]
I know that it is a "for" loop and it creates a "sentence" variable, but how does the loop know that it need to look in a key and value of hash "PHRASES"
And my second "wall" is:
question, answer = convert(snippet, phrase)
It looks like it creates and assigns "question" and "answer variables to the "convert" method with "snippet" and "phrase" parameters... again how does it assigns "question" to a key and answer to a value.
I know that this is probably very simple but as for now it blocks my mind :(
For your first question about the for-loop:
Look at where the for-loop is defined. It's inside the convert() method, right? And the convert() method is passed two arguments: one snippet and one phrase. So the loop isn't "looking" for values in the PHRASES hash, you are the one supplying it. You're using the method's arguments.
For your second question about assignment:
In Ruby we can do something called "destructuring assignment". What this means is that we can assign an array to multiple variables, and each variable will hold one value in the array. That's what's happening in your program. The convert() method returns a two-item array, and you're giving a name (question and answer) to each item in the array.
Here's another example of a destructuring assignment:
a, b, c = [1, 2, 3]
a # => returns 1
b # => returns 2
c # returns 3
Try this out in IRB and see if you get the hang of it. Let me know if I can help clarify anything, or if I misunderstood your question. You should never feel bad about asking "simple" questions!

Method that outputs hash value [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Say I have two hashes that share one key (for example "foo") but different values. Now I want to create a method with one attribute that puts out the value of the key depending on which hash I chose as attribute. How do I do that?
I have tried:
def put_hash(hash)
puts hash("foo")
end
but when I call this function with a hash it gives me the error below:
undefined method `hash' for main:Object (NoMethodError)
You need to access the value with []:
puts hash["foo"]
Otherwise Ruby thinks you're trying to invoke a method with (), and you're seeing an error because there is no method called hash in that scope.
Have you tried:
def put_hash(hash)
puts hash["foo"]
end
Or better yet:
def put_hash(hash)
puts hash[:foo]
end
Ruby stores the values in a hash like this:
{ :foo => "bar" }
or
{ "foo" => "bar" }
Depending if you use a Symbol or a String
To access them you need to call the [] method in the Hash class
The Ruby Docs are always a good starting point.
Write it as
def put_hash(hash)
puts hash["foo"]
end
h1 = { "foo" => 1 }
h2 = { "foo" => 2 }
put_hash(h2) # => 2
Look here Hash#[]
Element Reference—Retrieves the value object corresponding to the key object

Resources