Hi I have an array that i created using push like this
arr.push(h, s.power)
PS: h and s.power both are variables but depends on condition I applied
which ends up something like this
[22,"0.014",22,"0.01",22,"0.01",22,"0.082",22,"0.0002",22,"0.02822",22,"0.0042822",22,"0.041662",21,"0.0042822",21,"0.11107"]
but now I want to create new array for each new value like 22, 21 but I can not access it with many combinations I tried such as arr[22], with arr.map
You should consider using a Hash instead. See ruby hash documentation here.
So instead of pushing h and s.power into an array, you would add them to the hash like this:
my_hash[h] ||= []
my_hash[h].push(s.power)
The first line makes sure you have an array in the hash for the latest value of h. The second adds s.power to that array.
If you run this code repeatedly, you will end up with one array for each unique value of h which you can access like this:
my_hash[22] # <= returns the array of s.power values for h=22
my_hash[21] # <= returns the array of s.power values for h=21
If I understand your question correctly, this should be a clean way to do what you want.
Related
Hi I am find the average
This what I am trying to do
I have as set of variables which I am taking from db based upon user_id and company_id the variables are And I cannot added then and there because I need to display individual parameter in my show page and I also wanted to display their average
So I am trying to do as below
#r1=company_rating.collect(&:r1)
#r2=company_rating.collect(&:r2)
#r3=company_rating.collect(&:r3)
#r4=company_rating.collect(&:r4)
So I am doing it like
arr = [#r1,#r2,#r3,®r4]
#totalaverage= arr.sum.compact /arr.size
My array sample looks like [10,20,30,nil],[nil,nil,nil,nil],[30,40,50,60]
And If I have array all Nil then it should show be Nil
But I am getting an error undefined method `/' for # and Why I am doing compact is because I have sum of the nil values in that
So please help how do this.
First of all, you define arr as an array of arrays. #r1, #r2 etc. are all arrays and what [#r1, #r2, ...] does is just mixing them up in another array. You probably want to merge them, not include them in another array:
arr = #r1 + #r2 + #r3 + #r4
Second, you should call arr.compact first, then sum the contents up. Also, I'm not really sure about the sum method. I'd use reduce(&:+) instead. So, to answer your question, '/' fails because compact returns an Array, and you're trying to divide an Array to a number. This looks better:
arr = #r1 + #r2 + #r3 + #r4
#totalaverage = arr.compact.reduce(&:+) / arr.size
What Array#reduce(&:+) does is to apply the + operator between array members and return the value (not an array).
EDIT: arr.sum does work if you're using Ruby on Rails. Otherwise use arr.reduce(&:+) instead.
Do as below,which should work :
#totalaverage= arr.flat_map(&:compact).inject(:+) /arr.size.to_f
Actually #totalaverage is an array of array. Where each internal element(array) of #totalaverage can have nil values also(as you shown). So you need to remove those nil entries if any from the internal array of #totalaverage. And arr.map(&:compact) will do the same job.
Simplest way to do this if you're using Rails:
#totalaverage = a.flatten.compact.sum.to_f / a.flatten.compact.size if a.flatten.compact.present?
This will assign to #totalaverage the result or nil in case all the values are nil.
I've got an hash that looks like this
{"1-5 lbs"=>107342.43999999999, "31+ lbs"=>39838.58000000001, "21-30 lbs"=>19036.41, "11-20 lbs"=>39350.95, "6-10 lbs"=>41401.880000000005}
And I'd like to sort it so it looks like this
{"1-5 lbs"=>107342.43999999999, "6-10 lbs"=>41401.880000000005, "11-20 lbs"=>39350.95, "21-30 lbs"=>19036.41, "31+ lbs"=>39838.58000000001 }
The logic is being stored in an instance variable #weight_ranges
You'll need to get into regular expressions to get the value of the first number of each
range.
Hash[(#weight_ranges.sort_by {|key, value| key.scan(/\d+/)[0].to_i})]
To break it down further:
# Sort the weight ranges by the first series of digits found in the key
x = #weight_ranges.sort_by {|key, value| key.scan(/\d+/)[0].to_i}
# Convert each inner Array to a key, value pair in a Hash
x = Hash[x]
You depicted the data as a hash. For a sequence you'll need an array of pairs. Something like this will do it:
list_of_pairs = #weight_ranges.keys.sort_by(&:to_i).map {|k| [k, #weight_ranges[k]]}
This exploits a happy coincidence that to_i stops at the first non-digit it sees.
Correction
I have just learned that in 1.9 Ruby hashes are ordered! So it's easy to adapt:
Hash[#weight_ranges.sort_by{|k,v| k.to_i}]
I'll leave both ideas here, since the first one is still right for Ruby < 1.9.
My goal is to determine whether there is a blank in a hash like this:
{"departure_time_slots"=>{"date"=>[""], "time"=>{"start"=>[""], "end"=>[""]}}}
The strings are nested arbitrary times. I do not want to check each of them manually. It would be nice if I can extract all the strings regardless of their depth. Is there a simple way to do that?
Here's an example of how you can extract the values. However you will still have the problem of matching the values to the keys. You can't really have both at the same time.
# Extend the Hash class
class Hash
def recursive_values
self.values.collect { |v|
v.is_a?(Hash) ? v.recursive_values : v
}.flatten
end
end
Usage:
h = {"departure_time_slots"=>{"date"=>[""], "time"=>{"start"=>[""], "end"=>[""]}}}
h.recursive_values
=> ["", "", ""]
It will be better if you will use sth like that:
departure_time_slots = {:date => Time.new, :time_start => nil, :time_end => nil}
And when you use keys in Hash it is good practise to using Symbols for keys. (http://www.ruby-doc.org/core-1.9.3/Symbol.html)
No not possible. Because they are totally present in different scope with respect to each other.
For e.g.. keys start and end is totally unknown and masked from the departure_time_slots object in the example above.
One round abut way could be, getting all the values of the hashmap which are of type hashmap again and obtaining their keys recusively.
Fetch keys of departure_time_slots and then from the value list of that map, find all the keys from every value, if that were to be a hashmap. Other than that, I don't think there is another way.
P.S. On side note, see if u can modify your structure to an array where elements can also be arrays, and try and use flatten concept of arrays. :P
I have an AR query that returns a hash of events per month, ordered by month
o.events.group("to_char(date,'MM')").order("to_char(date,'MM')").size()
I'm using numeric months in this query as it was the best way I could find to get things in the correct order, and I also need to do some other manipulations on the hash.
Before display the results, I need to convert the numeric months back to words. I added the following to the end of the query
.each_key{ |key| Date::MONTHNAMES[key] }
But i get
TypeError: can't convert String into Integer.
So i tried
.each_key{ |key| Date::MONTHNAMES[key.to_i] }
But the months remain in numeric form
{"01"=>4, "02"=>3.....
How can i manipulate this hash to get
{"January"=>4, "February"=>3.....
Make a new Hash. If you can't, make a new key in the current hash and delete the original key. You can't simply change a key, since key is a local variable in the block, and changing it in no way impacts the contents of the Hash.
This ? :
def number_to_month(number)
(Time.now.beginning_of_year + number.months).strftime("%B")
end
There are ways to generate a new hash but I think you could just convert the strings to month names in your view right before displaying them. Use the code you already wrote inside the block in your question but put it in your view.
Is there a simple way, instead of looping my entire array to fetch the first value of every inner array.
so in essence I have the following;
array = [['test', 'test2'...], ['test' ....]]
so I want to grab array[#][0] and store the unqiue values.
EDIT
Is there a similar way to use the transpose method for arrays with Hash?
I essentially want to do the same thing
Hash = {1=> {1=> 'test', .....}, 2=> {1=> 'test',....}
so at the end I want to have something like new hash variable and leave my existing hash within hash alone.... = {1 => 'test', 2=> 'test2'}
Not sure if I fully understand the question, but if you have a 2 dimensional array (array in array), and you want to turn that into an array of the first element of the second dimension, you can use the map function
firsts = array.map {|array2| array2.first}
The way map works is that it turns one collection into a second collection by applying a function you provide (the block) to each element.
Maybe this?
array.transpose[0]