Reputation: 45
I am a newbie to coding and to ruby and have an assignment for class. We are supposed to take a data set from excel of taxi drivers and find the number of rides and amount earned per driver. We are free to structure the code in any way we want. Below is my code.
What I am trying to do is tally the number of rides and store them in the hash rides_per_driver
. However, with the if
statement I get a "no implicit conversion of Array into Integer (TypeError)." How do I get the program to take the keys
for rides_per_driver
and iterate over the hash rides
?
Any help is appreciated. Thank you
# Stored rides data.
rides = {
ride_1: {
driver_id: "DR0004",
date: "3rd Feb 2016",
cost: 5,
rider_id: "RD0022",
rating: 5
},
ride_2: {
driver_id: "DR0001",
date: "3rd Feb 2016",
cost: 10,
rider_id: "RD0003",
rating: 3
},
ride_3: {
driver_id: "DR0002",
date: "3rd Feb 2016",
cost: 25,
rider_id: "RD0073",
rating: 5
}
}
# iterate over the hash of hashes. If the driver id is x then
# add one ride to the tally.
# Storage for number of rides per driver
rides_per_driver = {
"DR0001" => 0,
"DR0002" => 0,
"DR0003" => 0,
"DR0004" => 0
}
amount_earned_per_driver = []
rides_per_driver.each do |x|
if rides_per_driver.has_key?(rides_per_driver[x])
rides.each do|ride_num, ride_data|
rides.each do |k, v|
rides_per_driver += 1
end
end
else
rides.each do|ride_num, ride_data|
rides.each do |k, v|
rides_per_driver = 1
end
end
end
end
Upvotes: 1
Views: 1154
Reputation: 104111
First, let's change the data you have to two drivers with one, "DR0004"
, having two rides:
rides = {
ride_1: {
driver_id: "DR0004",
date: "3rd Feb 2016",
cost: 5,
rider_id: "RD0022",
rating: 5
},
ride_2: {
driver_id: "DR0004",
date: "3rd Feb 2016",
cost: 10,
rider_id: "RD0003",
rating: 3
},
ride_3: {
driver_id: "DR0002",
date: "3rd Feb 2016",
cost: 25,
rider_id: "RD0073",
rating: 5
}
}
You can use .group_by
to get a hash of drive drives by driver:
rides_by_driver=rides.group_by { |k, h| h[:driver_id] }
.map { |k, v| [k, v.to_h] }.to_h
{"DR0004"=>{:ride_1=>{:driver_id=>"DR0004", :date=>"3rd Feb 2016", :cost=>5, :rider_id=>"RD0022", :rating=>5}, :ride_2=>{:driver_id=>"DR0004", :date=>"3rd Feb 2016", :cost=>10, :rider_id=>"RD0003", :rating=>3}}, "DR0002"=>{:ride_3=>{:driver_id=>"DR0002", :date=>"3rd Feb 2016", :cost=>25, :rider_id=>"RD0073", :rating=>5}}}
Then you can add up the amounts per driver:
rides_by_driver.map { |k,v| [k, v.inject(0) { |sum,(k,v)| sum+=v[:cost] } ] }.to_h
{"DR0004"=>15, "DR0002"=>25}
Or, if you want to know the rides per driver:
rides_by_driver.map { |k,v| [k, v.length] }.to_h
{"DR0004"=>2, "DR0002"=>1}
Upvotes: 1
Reputation: 110755
rides = [
{ driver_id: "DR0004", date: "3rd Feb 2016", cost: 5, rider_id: "RD0022", rating: 5 },
{ driver_id: "DR0001", date: "3rd Feb 2016", cost: 10, rider_id: "RD0003", rating: 3 },
{ driver_id: "DR0002", date: "3rd Feb 2016", cost: 25, rider_id: "RD0073", rating: 5 },
{ driver_id: "DR0004", date: "3rd Feb 2016", cost: 5, rider_id: "RD0022", rating: 5 },
]
rides.each_with_object({}) do |ride, h|
h.update(ride[:driver_id]=>{ rides: 1, earnings: ride[:cost] }) do |_,o,n|
{ rides: o[:rides]+1, earnings: o[:earnings]+n[:earnings] }
end
end
#=> {"DR0004"=>{:rides=>2, :earnings=>10},
# "DR0001"=>{:rides=>1, :earnings=>10},
# "DR0002"=>{:rides=>1, :earnings=>25}}
This uses the form of Hash#update (aka merge!
) that employs a block to determine the values of keys present in both hashes being merged. See the doc for details, especially the definitions of the three block variables (_
, o
and n
). (I've used an underscore in place of the common key to signify that the key is not used in the block calculation.)
Upvotes: 2
Reputation: 400
rides = {
ride_1: {
driver_id: 'DR0004',
date: '3rd Feb 2016',
cost: 5,
rider_id: 'RD0022',
rating: 5
},
ride_2: {
driver_id: 'DR0001',
date: '3rd Feb 2016',
cost: 10,
rider_id: 'RD0003',
rating: 3
},
ride_3: {
driver_id: 'DR0002',
date: '3rd Feb 2016',
cost: 25,
rider_id: 'RD0073',
rating: 5
}
}
# iterate over the hash of hashes. If the driver id is x then
# add one ride to the tally.
# Storage for number of rides per driver
rides_per_driver = {
'DR0001' => 0,
'DR0002' => 0,
'DR0003' => 0,
'DR0004' => 0
}
amount_earned_per_driver = []
I think this all you need to do to get your rides_per_driver
updated
rides.each do |_key, val|
rides_per_driver[val[:driver_id]] += 1
end
You iterate through the rides and get the rider_id
for each ride which is val[:driver_id]
in the solution. You then use it to update the value of each driver in rides_per_driver.
Upvotes: 1