Sending one line of hash to method - ruby

I have an array with words that I will use as keys. I iterate trough this array and put the words as keys and user input as value simplified like this:
input = Hash.new()
array.each do |a|
input[a] = gets.strip
end
for example array ["one", "twoo", "three"]
and the user inputs first: three
I want to pass {"one" => "three"}
So the current key and value
Now I want to pass this "line" of the array to a method how do I do this ?

It is still unclear what you want to achieve. The way I see it, you can mean one of three things:
"I want to pass the key and value after the user enters them to a method"
array.each do |key|
input[key] = gets.strip
my_method(key, input[key])
end
A possible spin on that is "But I want to pass them as a single hash"
array.each do |key|
input[key] = gets.strip
my_method({key, input[key]})
end
"I want to pass the entire hash after the user fills all the values"
array.each do |key|
input[key] = gets.strip
end
my_method(input)

Just call that method and pass your "line":
input = Hash.new()
array.each do |a|
input[a] = gets.strip
# Send a line that user has inputed
your_method(input[a])
# Send key and the line that user has inputed
your_method(a, input[a])
end

I got an impression that you are not trying to pass the entire hash at a time. If so, here is the one line answer
arr.each{|x| my_method({x => gets.strip})}
If I am wrong and you want to pass it at a time. Here is the one line answer
my_method(Hash[arr.zip(arr.map{gets.strip})])

Related

Making a sorted array of user's input

I'm learning Ruby with 'Learn to Program' by Chris Pine. On chapter 10 I should write a program where the user types as many words as he like and when he's done, he can just press Enter on an empty line and exit.
I came up with this:
puts "Type whatever you want!"
index = 0
word = ''
array = []
while word != nil
word << gets.chomp
array[index] = word
index = index + 1
end
puts ''
puts array.sort
But that doesn't work. What did I miss? Is there another way I could define word without having to repeat it?
The word will not have nil value. It will be an empty string. So you need to check for that:
while word != ""
# or even better
while !word.empty?
Also, you are adding everything to your word. You probably want to assign to it instead:
word = gets.chomp
Per author's comment:
begin
# your code here
end while !word.empty?
# OR more readable
begin
# your code here
end until word.empty?
It seems like there's a simpler solution, if I'm reading the question correctly.
You could do something like this:
user_input = gets.chomp.split(" ").sort
ex)
input: bananas clementine zebra tree house plane mine
output: ["bananas", "clementine", "house", "mine", "plane", "tree", "zebra"]
Here's a simple loop that you could do just for kicks:
arr = []
arr << $_.strip until gets =~ /^\s*$/
puts arr.sort
$_ is a special variable that evaluates to the last input read from STDIN. So basically this reads "Call gets and check if the input is just spaces. If it is then break out of the loop, otherwise append the last input with whitespace removed value onto the array and continue looping."
Or even more fun, a one liner:
puts [].tap {|arr| arr << $_.strip until gets =~ /^\s*$/}.sort
Basically same thing as above except using tap to initialize the variable.
To answer your questions:
Is there another way I could define word without having to repeat it?
Use side effects of assignment. In ruby when you assign a variable the return value of that assignment is the assigned variable, as in:
irb(main):001:0> (variable = 2) == 2
=> true
The idea would be to put the assignment in the your conditional. If I were to write something like this in a comprehensible loop, as opposed to those above, I'd write something like this:
arr = []
while !(word = gets.strip).empty?
arr << word
end
puts arr.sort
Using loop might simplify the code:
a = []
loop do
input = gets.chomp
if input.empty?
break
else
a << input
end
end
a.sort!
puts a

Combining data parsed from within the same hash in Ruby

I'm trying to combine large data sets that I've filtered out from a single hash. I've tried various things such as merge, but don't seem to be able to get the data to combine the way I'm envisioning. Here are the things I'm trying to combine:
puts '','=========GET INFO'
print_data = targetprocess.comments_with_ids #get the hash
puts print_data #show the hash for verification
puts '','=========GET IDs'
story_ids = print_data['Comments']['Comment'].map {|entry| entry['General']} #filter for story ids and story name
puts story_ids
puts '','=========GET COMMENTS'
comment_description = print_data['Comments']['Comment'].map {|words| words['Description']} #get all comments, these are in the same order as the story ids
puts comment_description
Ultimately what I would like it to look like is:
story_id 1 + comment_description 1
story_id 2 + comment_description 2
etc.
Any help would be greatly appreciated.
I ended up realizing that the hash had some other nested structures I could use. In this example I use a nested hash, then store it as an array (I ultimately need this for other work) and then output.
puts '','=========GET INFO'
print_data = targetprocess.comments_with_ids #get the hash
puts print_data #show the hash for verification
puts '=========COMPLETE', ''
#=========HASH OF USEFUL DATA
results = {}
print_data['Comments']['Comment'].each{|entry|
results[entry['Id'].chomp] = {:parent_id => entry['General']['Id'].chomp, :description => entry['Description'].chomp}}
#=========STORE HASH AS AN ARRAY
csv_array = []
results.each{|key,value|
csv_array << [key, value[:parent_id], value[:description]]
#=======FRIENDLY OUTPUT
puts "Story_Id #{value[:parent_id]}, Comment_Id #{key}, Comment #{value[:description]}"}

Hash Parsing with Ruby

I have the array of hash as shown below:
#line_statuses = [
{:name=>"1", :status=>"online"},
{:name=>"2", :status=>"online"}
]
I'd like to parse each hash inside of #line_statuses array so that I can print out the name and status as shown below.
1: online
2: online
How would I go about doing this?
Technically your #line_statuses variable is an array, so what you have is an array of hashes. In Ruby, to iterate over an array we use the .each method. Then, in each iteration, we can access the values of the hash using the defined keys:
#line_statuses.each do |hash|
puts hash[:name]
puts hash[:status]
end
So simple...:
#line_statuses.each do |line_status|
puts "#{line_status[:name]}: #{line_status[:status]}"
end
try #line_statuses.each{|i| puts i[:name],i[:status]}
Pretty simple:
#line_statuses.each { |line_status| puts "#{line_status[:name]}: #{line_status[:status]}" }

Ruby-How to build a multivalued hash?

Here is my code snippet:
something_1.each do |i|
something_2.each do |j|
Data.each do |data|
date = data.attribute('TIME_PERIOD').text
value = data.attribute('OBS_VALUE').text
date_value_hash[date] = value
end
end
end
I want to capture all the values in a single date. date is the key of my hash and it may have multiple values for a single date. How can I accomplish that here? When I am using this line:
date_value_hash[date] = value
values are getting replaced each time the loop iterates. But, I want to accumulate all the values in my date_value_hash for each dates i.e. I want to build the values dynamically.
Currently I am getting this:
{"1990"=>"1", "1994"=>"2", "1998"=>"0"}
But, I want something like this:
{"1990"=>"1,2,3,4,5,6", "1994"=>"1,2,3,4,5,6", "1998"=>"1,2,3,4,5,6"}
Anyone have any idea how can I accomplish that?
Like this
magic = Hash.new{|h,k|h[k]=[]}
magic["1990"] << "A"
magic["1990"] << "B"
magic["1994"] << "C"
magic["1998"] << "D"
magic["1994"] << "F"
after which magic is
{"1998"=>["D"], "1994"=>["C", "F"], "1990"=>["A", "B"]}
and if you need the values as comma separated string (as indicated by your sample data), you'll just access them as
magic['1990'].join(',')
which yields
"A,B"
if later you want to pass magic around and preventing it from automagically creating keys, just wrap it as follows
hash = Hash.new.update(magic)
Hope that helps!
Another approach of building multi-valued hash in Ruby:
h = {}
(h[:key] ||= []) << "value 1"
(h[:key] ||= []) << "value 2"
puts h

string to object?

Consider the following code:
I receive an object from datamapper which contains Values from my select:
user = User.first()
puts user.name
# John
puts user.surname
# Doe
puts user.age
# 42
In a user defined Array I have an Order for these Values to be displayed
dataordering = ["age", "surname", "name"]
So how do I get my values ordered as in my Array?
dataordering.each do |sequence|
puts user.sequence
# this, of course, fails
end
I don't want to use eval(). nope.
Maybe there's even a better way to store an ordering of values?
You can pick values from record this way:
user_attributes = user.attributes
dataordering.each do |attribute|
puts user_attributes[attribute.to_sym]
end
Or use send method:
dataordering.each do |attribute|
puts user.send attribute.to_sym
end
As an ordering solution, I can offer you this code:
dataordering.map { |attr| user.send attribute.to_sym }

Resources