Sort rails hash based on array of items - ruby-on-rails

I have an array like this:
['one','three','two','four']
I have a array of hash like this:
[{'three' => {..some data here..} }, {'two' => {..some data here..} }, {:total => some_total }] # etc...
I want to sort the array of hashes by the first array. I know I can do:
array_of_hashes.sort_by{|k,v| k.to_s} to sort them and it will sort by the key
( and the .to_s to convert :total to a string )
How can I make this happen?
Edit:
I was incorrect about how this is setup, it is actually like this:
{'one' => {:total => 1, :some_other_value => 5}, 'two' => {:total => 2, :some_other_value => 3} }
If I need to put this in a new question, just let me know and I will do that.
Thank you

similar to ctcherry answer, but using sort_by.
sort_arr = ['one','three','two','four']
hash_arr = [{'three' => {..some data here..} }, {'two' => {..some data here..} }]
hash_arr.sort_by { |h| sort_arr.index(h.keys.first) }

The index method of Array is your friend in this case:
sort_list = ['one','three','two','four']
data_list = [{'three' => { :test => 3 } }, {'two' => { :test => 2 } }, {'one' => { :test => 1 } }, {'four' => { :test => 4 } }]
puts data_list.sort { |a,b|
sort_list.index(a.keys.first) <=> sort_list.index(b.keys.first)
}.inspect
Resulting in, the same order as the source array:
[{"one"=>{:test=>1}}, {"three"=>{:test=>3}}, {"two"=>{:test=>2}}, {"four"=>{:test=>4}}]

Related

Grabbing a specific hash in an array that meets a specific criteria

I have a huge array full of a bunch of hashes. What I need to do is single out one index hash from the array that meets a specific criteria. (doing this due to an rspec test, but having trouble singling out one of them)
My array is like this
[
{
"name" => "jon doe",
"team" => "team2",
"price" => 2000,
"eligibility_settings" => {}
},
{
"name" => "jonny doe",
"team" => "team1",
"value" => 2000,
"eligibility_settings" => {
"player_gender" => male,
"player_max_age" => 26,
"player_min_age" => 23,
"established_union_only" => true
}
},
{
"name" => "jonni doe",
"team" => "team3",
"price" => 2000,
"eligibility_settings" => {}
},
]
I need to single out the second one, based on its eligibility settings. I just took three of them from my array, have lots more, so simple active record methods like (hash.second) won't work in this instance.
I've tried things like
players.team.map(&:hash).find{ |x| x[ 'eligibility_settings?' ] == true}
However when I try this, I get a nil response. (which is odd)
I've also looked into using the ruby detect method, which hasn't gotten me anywhere either
Players.team.map(&:hash).['hash.seligibiltiy_settings'].detect { true }
Would anybody have any idea what to do with this one?
Notes
players.team.map(&:hash).find{ |x| x[ 'eligibility_settings?' ] == true}
Players.team.map(&:hash).['hash.seligibiltiy_settings'].detect { true }
Is is players or Players ?
Why is it plural?
If you can call map on team, it probably should be plural
Why do you convert to a hash?
eligibility_settings? isn't a key in your hash. eligibility_settings is
eligibility_settings can be a hash, but it cannot be true
If you want to check if it isn't empty, use !h['eligibility_settings'].empty?
Possible solution
You could use :
data = [
{
'name' => 'jon doe',
'team' => 'team2',
'price' => 2000,
'eligibility_settings' => {}
},
{
'name' => 'jonny doe',
'team' => 'team1',
'value' => 2000,
'eligibility_settings' => {
'player_gender' => 'male',
'player_max_age' => 26,
'player_min_age' => 23,
'established_union_only' => true
}
},
{
'name' => 'jonni doe',
'team' => 'team3',
'price' => 2000,
'eligibility_settings' => {}
}
]
p data.find { |h| !h['eligibility_settings'].empty? }
# {"name"=>"jonny doe", "team"=>"team1", "value"=>2000, "eligibility_settings"=>{"player_gender"=>"male", "player_max_age"=>26, "player_min_age"=>23, "established_union_only"=>true}}
If h['eligibility_settings'] can be nil, you can use :
data.find { |h| !h['eligibility_settings'].blank? }
or
data.find { |h| h['eligibility_settings'].present? }

dynamic loop in a hash Ruby on Rails

I'm trying to create a dynamic loop within the hash #data below and
can't really seem to figure it out. I'm creating an annotatedtimeline-for-rails using the google api from here https://github.com/mcommons/annotatedtimeline-for-rails.
The array within the hash #data has to be dynamic i:e the day number has to be generated by a loop and the name of the product and number are dynamic as well. I'll
try to give an example in the loop below
#numdeployed is a number and comes from a table in the db
i should be generated by the loop
#data{
begin loop
i.day.ago.to_date => { :foo=>#numdeployed, :bar=>#numdeployed, :barbaz=>#numdeployed, :foobar=>#numdeployed },
end loop
}
The Original Data Hash looks like this
#data = {
1.day.ago.to_date => { :foo=>10, :bar=>40, :barbaz=>10, :foobar=>40 },
2.day.ago.to_date => { :foo=>10, :bar=>40, :barbaz=>10,:foobar=>40 },
3.day.ago.to_date => { :foo=>10, :bar=>40, :barbaz=>10,:foobar=>40 },
4.day.ago.to_date => { :foo=>10, :bar=>40, :barbaz=>10,:foobar=>40 },
5.day.ago.to_date => { :foo=>10, :bar=>40, :barbaz=>10,:foobar=>40 }
}
hope someone can help. Thanks
Are you looking for something like this?
#data = Hash[
n.times.map do |i|
[ (i + 1).day.ago.to_date, { :foo => 10, :bar => 40, :barbaz => 10, :foobar => 40 } ]
end
]
The n is however many pairs you want in your #data.

Ruby how to sort hash of hashes?

I have that deep Hash of hashes:
my_hash = {
:category_1 => {
:solution_1 => { :order => 1 },
:solution_2 => { :order => 2 }
},
:category_2 => {
:solution_3 => { :order => 3 },
:solution_4 => { :order => 4 }
}
}
I want to sort :solution_* hashes under :category_* hashes by key :order. Any suggestions?
(fixed)
Let's say you have the following hash of people to ages:
people = {
:fred => { :name => "Fred", :age => 23 },
:joan => { :name => "Joan", :age => 18 },
:pete => { :name => "Pete", :age => 54 }
}
use sort_by to get where we want to go:
people.sort_by { |k, v| v[:age] }
# => [[:joan, {:name=>"Joan", :age=>18}],
[:fred, {:name=>"Fred", :age=>23}],
[:pete, {:name=>"Pete", :age=>54}]]
Ok, you didn't specify your question, so I'm assuming you want one layer removed. I changed the starting hash a bit to actually see if the sorting works:
my_hash = {
:category_1 => {
:solution_1 => { :order => 2 },
:solution_2 => { :order => 3 }
},
:category_2 => {
:solution_3 => { :order => 4 },
:solution_4 => { :order => 1 }
}
}
Hash[my_hash.inject({}) { |h, (k, v)| h.merge(v) }.sort_by { |k,v| v[:order] }]
#=> {:solution_4=>{:order=>1}, :solution_1=>{:order=>2}, :solution_2=>{:order=>3}, :solution_3=>{:order=>4}}
EDIT:
Taking into account your clarification (and still starting from the modified unsorted hash I posted above):
sorted = my_hash.inject({}) do |h, (k, v)|
h[k] = Hash[v.sort_by { |k1, v1| v1[:order] }]
h
end
#=> {:category_1=>{:solution_1=>{:order=>2}, :solution_2=>{:order=>3}}, :category_2=>{:solution_4=>{:order=>1}, :solution_3=>{:order=>4}}}

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

How can I grab certain values in a hash in Ruby?

I have a hash
hash = { 1=> { 0=> 'apple', 1=> 'tree'... ....}, 2=> {.....}}
I want to grab the 0 for all hashes within the hash. I know there is a transpose for array, but there any way to do this with a hash easily?
Something like this should work:
hash.values.collect{|v| v[0]}
Example:
irb(main):001:0> hash = { 1 => { 0 => 'apple', 1 => 'tree' },
2 => { 0 => 'foo', 1 => 'bar' }}
=> {1=>{0=>"apple", 1=>"tree"}, 2=>{0=>"foo", 1=>"bar"}}
irb(main):002:0> hash.values.collect{|value| value[0]}
=> ["apple", "foo"]

Resources