How to get each value from hash of array? - ruby-on-rails

I have a hash of array with key, values in ruby which I want to pass each value with key. I want to extract content using my hash. My code is :
def get_content
GetPageContent.new(#pdf.id, session[:selected_pages][#document.id.to_s])
end
in session[:selected_pages] I got like this
{"15"=>["001"], "24"=>["001","005"]}
In this first value is pdf id and second value is page number of that pdf.
I want this :
GetPageContent.new(#pdf.id, session[:selected_pages][#document.id.to_s])
I want to pass all values like this:
GetPageContent.new(15, 001)
GetPageContent.new(24, 001)
GetPageContent.new(24, 005)
How to map each key values from hash of array?

A simple nested loop will suffice:
session[:selected_pages].each do |pdf_id, page_numbers|
page_numbers.each { |page_number| GetPageContent.new(pdf_id, page_number) }
end

You can use something like this
hsh = {"15"=>["001"], "24"=>["001","005"]}
hsh.each(&->(page, pages){pages.each{|id| GetPageContent.new(id, page)}})

You could do something like this to get a simple array. h is your hash
pages = h.flat_map { |key, arr| ([key] * arr.size).zip(arr) }
=> [["15", "001"], ["24", "001"], ["24", "005"]]
pages.map! { |pdf_id, page_number| GetPageContent.new(pdf_id, page_number) }

session[:selected_pages]
.map{|k, v| [k].product(v)}.flatten(1)
# => [["15", "001"], ["24", "001"], ["24", "005"]]
The rest is up to you.

Related

how to check if a certain key-value pair exists in array of hashes as json in ruby on rails

I have an array of hashes as json, so how to check my array of hashes contains a hash with a given key-value pair.
This is my json
[{"question"=>"0a2a3452", "answer"=>"bull"}, {"question"=>"58deacf9", "answer"=>"bullafolo"}, {"question"=>"32c53e5f", "answer"=>"curosit"}, {"question"=>"b5546bcf", "answer"=>""}, {"question"=>"0f0b314", "answer"=>""}]
I tried looping through the json array, but this is tedious, as I need to check that if that json has that hash with a given key-value pair
It's a questionnaire form, in which I have to perform an update on answers
if !#client_find.nil?
#client_find.questionnaire
params[:commit].each do |key, value|
#json=[]
#json = #client_find.questionnaire
if !value.empty? && #json.include?(key)
puts "blunderc "+ value.inspect
#new_append = Hash.new
#new_append[:question] = key
#new_append[:answer]= value
#json << #new_append
end
if !key.empty? && !value.empty?
#logic
#json.each do |u|
if (u.key? key)
puts "bothu "+ u[key].inspect
u[key] = value
end
end
end
end
Array#any? iterates through the array. In each iteration I check wether the current hash has the searched question key or not. If a hash is found Array#any? returns true otherwise false.
array = [{"question"=>"0a2a3452", "answer"=>"bull"}, {"question"=>"58deacf9", "answer"=>"bullafolo"}, {"question"=>"32c53e5f", "answer"=>"curosit"}, {"question"=>"b5546bcf", "answer"=>""}, {"question"=>"0f0b314", "answer"=>""}]
search_for_key = '0a2a3452'
array.any?{|hash| hash['question'] == search_for_key}
I'll assume that you want to check the existence of a hash which has the key/value pair "quesetion" => "some-value".
Here's how you can do it:
array.any? { |item| item['question'] == 'some-question-id' }
Considering your are checking for a particular key exists or not
#json.any? {|obj| obj.key?(your_particular_key)
You can filter the array using Enumerable#select to get only the hashes that contains the desired key.
filtered = my_hash.select { |item| item['desired_key'] }
That's possible because nil is falsey. If you input is a raw JSON you'll need to parse it to a Ruby hash using JSON#parse or any other equivalent method.
filtered will give you all the hashes that contain the desired_key.
Is that what you want ?
Btw guitarman's answer is way better !
questions = [{"question"=>"0a2a3452", "answer"=>"bull"}, {"question"=>"58deacf9", "answer"=>"bullafolo"}, {"question"=>"32c53e5f", "answer"=>"curosit"}, {"question"=>"b5546bcf", "answer"=>""}, {"question"=>"0f0b314", "answer"=>""}]
result = questions.find { |question| question['question'] == "Bonour" }
if result.nil?
puts "Not found"
else
puts "#{result['question']} #{result['answer']}"
end

How can I get the value of the name only on this array?

This is the output array when I do
result = JSON.parse(response.body)
result.values.each {|element|
puts element
}
Result:
{"id"=>3, "code"=>"3", "name"=>"Market", "status"=>"A", "refcode"=>"001"}
{"id"=>4, "code"=>"4", "name"=>"Mall", "status"=>"A", "refcode"=>"002"}
From this array, I only want to get the name value. I tried this
puts result['data'][0]['name'] and it worked fine but I want to get all the name in the array
This is my expected output
Market
Mall
Try using Array#map and over each element, to access it's 'name' key, like:
p array.map { |element| element['name'] }
# ["Market", "Mall"]
I think it'd be something like:
result = JSON.parse(response.body)
result.values.map { |element| element['name'] }
# ["Market", "Mall"]
Since with each and puts you're only iterating and printing the hashes in the array, you could access the 'name' key from result.values.
I wont modify much. Since your name element is at position 3. access it like array because you are using values.each
result = JSON.parse(response.body)
result.values.each {|element|
puts element[2]
}

Splitting values in Hash

I have a Hash in the following format:
{"PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548", "6e90208e-4ab2-4d44-bbaa-9a874bff095b"], "Amount"=>"[\"10000.000\", \"2374.000\"]"}
When I write this data into an excel get the following output.
I want to write the data into the Excel this way:
PPS_Id Amount
fe4d7c06-215a-48a7-966d-19ab58976548 10000.000
6e90208e-4ab2-4d44-bbaa-9a874bff095b 2374.000
How do I convert my current Hash to the below?
{PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548","Amount"=>"10000.000"},{PPS_Id"=>["6e90208e-4ab2-4d44-bbaa-9a874bff095b","Amount"=>"2374.000"}
Can you please assist.
If you can modify your original hash from
hash = {"PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548", "6e90208e-4ab2-4d44-bbaa-9a874bff095b"], "Amount"=>"[\"10000.000\", \"2374.000\"]"}
to
hash = {"PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548", "6e90208e-4ab2-4d44-bbaa-9a874bff095b"], "Amount"=>["10000.000", "2374.000"]}
Note: the last value in the hash is an Array instead of a String.
Then, you can generate an Array of hashes on which you can iterate to fill your excel:
ary = hash.inject([]) do |r, (key, value)|
value.each_with_index do |e, i|
r[i] ||= {}
r[i][key] = e
end
r
end
ary # [{"PPS_Id"=>"fe4d7c06-215a-48a7-966d-19ab58976548", "Amount"=>"10000.000"}, {"PPS_Id"=>"6e90208e-4ab2-4d44-bbaa-9a874bff095b", "Amount"=>"2374.000"}]
If your hash really looks like this :
hash = {"PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548", "6e90208e-4ab2-4d44-bbaa-9a874bff095b"],
"Amount"=>"[\"10000.000\", \"2374.000\"]"}
you can use scan to parse the floats first :
hash["Amount"] = hash["Amount"].scan(/[\d\-\.]+/)
Your hash will now look like :
{"PPS_Id"=>["fe4d7c06-215a-48a7-966d-19ab58976548", "6e90208e-4ab2-4d44-bbaa-9a874bff095b"],
"Amount"=>["10000.000", "2374.000"]}
To get the table you want, you could just transpose the hash values :
hash.values_at("PPS_Id", "Amount").transpose.each{|id, amount|
puts format("%s\t%.3f", id, amount)
}
It will output :
fe4d7c06-215a-48a7-966d-19ab58976548 10000.000
6e90208e-4ab2-4d44-bbaa-9a874bff095b 2374.000

Rails array sort

I have in rails this array:
#array = [{'82'=>'1'}, {'81'=>'0'},{'32'=>'12'}]
How can I sort it to have that result? I want to have this:
#array = [{'32'=>'12'}, {'82'=>'1'},{'81'=>'0'}]
and next - how then I can get #array[0] hash key (32)
This is an array of hash where hash is {'user_id'=>'counter'}
This will sort the array by value, in descending order, in place:
array.sort! { |h1, h2| h2.values.first <=> h1.values.first }
It can also be done with sort_by! followed by reverse!.
array.sort_by! { |h| h.values } .reverse!
Then, these will get you the first value and first key, respectively:
array.first.values.first
array.first.keys.first
Just append keys.sort to the end of the array. Use #array.keys.sort
#array.sort { |x,y| x.keys.first <=> y.keys.first }
Try using Enumerable#sort_by, and Array#reverse! to change the order.
> #array.sort_by { |h| h.values.first }.reverse!
=> [{"32"=>"12"}, {"82"=>"1"}, {"81"=>"0"}]

Converting http_params to hash

I can obtain an array from the string
http_params="created_end_date=2013-02-28&created_start_date=2013-01-01&page_size=50&offset=0&order_id=0D1108211501118%0D%0A0D11108211501118%0D%0Ac%0D%0AD%0D%0ADK212071409743%0D%0AKK30109110100%0D%0AKK30111140300%0D%0AKK30111140400%0D%0AKK30115120100%0D%0AKK30115150100&page_number=1"
So I did myarray=http_params.split("&"):
myarray=["created_end_date=2013-02-28", "created_start_date=2013-01-01", "page_size=50", "offset=0", "order_id=0D1108211501118%0D%0A0D11108211501118%0D%0Ac%0D%0AD%0D%0ADK212071409743%0D%0AKK30109110100%0D%0AKK30111140300%0D%0AKK30111140400%0D%0AKK30115120100%0D%0AKK30115150100", "page_number=1"]
I need to convert this to a hash myhash, so that I can make a Rest Client post call for myhash.to_json. Basically it should be key,value pairs like:
{:created_end_date=>"2013-02-28",:created_start_date=>"2013-01-01"....}
I know that the inverse operation can be done like this:
http_params = myhash.map{|k,v| "#{k}=#{v}"}.join('&')
but I am unable to come up with neat code for this.
What's the best way I should go about this?
require 'cgi'
hash = CGI::parse http_params
Or you can use:
hash = Rack::Utils.parse_nested_query http_params
Which does not return the values as arrays.
With pure Ruby methods, you can convert your string into a Hash as follows:
"a=1&b=2".split('&').map { |h| Hash[*h.split("=")] }
=> [{"a"=>"1"}, {"b"=>"2"}]
A blog post how to operate on Ruby collections is here: http://thinkingonthinking.com/map-reduce-in-ruby/
To get symbols as keys, a small additional step is necessary:
"a=1&b=2".split('&').map { |h| hs = h.split("="); Hash[hs[0].to_sym, hs[1]] }
=> [{:a=>"1"}, {:b=>"2"}]
As last step, a merge of the inner Hash elements has to be done. This can be done like:
"a=1&b=2".split('&').map { |h| hs = h.split("="); Hash[hs[0].to_sym, hs[1]] }.inject({}) { |s, h| s.merge(h) }
=> {:a=>"1", :b=>"2"}

Resources