Reputation: 3912
mydata = {:data => [
{
:first_name = > "abc",
:foo_id = > "21sd",
:roll = > 43
},
{:first_name = > "def",
:foo_id = > "2uf",
:roll = > 81
},
{:first_name = > "xyz",
:foo_id = > "ac32",
:roll = > 2
}
]
}
In mydata :roll has somehow corrupted value
I have a sorted hash, this has data as :foo_id => :roll
sorted = {"21sd" => 7, "ac32" => 89, "2uf" => 92}
(that is by sorted ascending correct value of :roll)
And I want to use this 'sorted' hash to rearrange 'mydata' and also over-ride the value of :roll
in 'mydata' with the correct value from 'sorted' hash. So finally 'mydata' will look like
mydata = {:data => [
{
:first_name = > "abc",
:foo_id = > "21sd",
:roll = > 7
},
{:first_name = > "xyz",
:foo_id = > "ac32",
:roll = > 89
},
{:first_name = > "def",
:foo_id = > "2uf",
:roll = > 92
}
]
}
UPADTE: :roll may not be unique in sorted
Consider mydata may have 100,000 hashes
I have achieved the result using nested loop of 'sorted' and in each iteration, searching the foo_id from 'mydata' and correcting the value and stroring the sorted data in new variable. Which is ugly.
correct = []
sorted.each {|k, v|
mydata[:data].each {|h| # hate looping here
if h[:foo_id] == k # hate searching here, if i have 100,000 record in 'mydata'
h[:roll] = v
correct << h
end
}
}
mydata = {:data => correct}
This is not an optimal solution if mydata contains large numbers of data sets. Anyone suggest some optimal solution?
Upvotes: 0
Views: 98
Reputation: 16730
data = [
{
:first_name => "abc",
:foo_id => "21sd",
:roll => 7
},
{:first_name => "xyz",
:foo_id => "ac32",
:roll => 89
},
{:first_name => "def",
:foo_id => "2uf",
:roll => 92
}
]
sorted = {"21sd" => 7, "ac32" => 89, "2uf" => 92}
foo_id_name = data.map do |rec|
{ rec[:foo_id] => rec[:first_name] }
end.reduce(&:merge)
new_data = sorted.map do |foo_id, new_roll|
{
:first_name => foo_id_name[foo_id],
:foo_id => foo_id,
:roll => new_roll
}
end
puts new_data.inspect #=> [{:first_name=>"abc", :foo_id=>"21sd", :roll=>7}, {:first_name=>"xyz", :foo_id=>"ac32", :roll=>89}, {:first_name=>"def", :foo_id=>"2uf", :roll=>92}]
Upvotes: 0
Reputation: 19899
This should work...
mydata[:data].each do |h|
h[:roll] = sorted[h[:foo_id]]
end
There's no way to avoid looping through mydata[:data] though as it's an Array... but you don't need to stuff things into a new variable.. just update what you've got.
Unless I'm not understanding the problem...
EDIT: I wasn't picking up the sorting right. New solution:
mydata[:data].each do |h|
h[:roll] = sorted[h[:foo_id]]
end
mydata[:data].sort_by!{|h| h[:roll]}
Upvotes: 2