Reputation: 408
I've looked on StackOverflow but haven't found any places that talk about taking the average of a specific Int or Double within a dictionary. This is my custom dictionary I've created:
var allInformationByDate = [
"1989-06-20": DayData(sales: 0, doorsKnocked: 0, milesWalked: 0.00, hoursWorked: 0.00),
"2016-06-22": DayData(sales: 2, doorsKnocked: 30, milesWalked: 2.00, hoursWorked: 3.00),
"2016-08-16": DayData(sales: 4, doorsKnocked: 30, milesWalked: 10.00, hoursWorked: 0.00)
]
So I would be looking to get the averages for each of these. For example:
var avgSales = average(sales) = 2
var avgDoors = average(doorsKnocked) = 20
var avgMiles = average(milesWalked) = 4.0
var avgHours = average(hoursWorked) = 1.0
Anybody know the syntax? Thanks for helping a noob!
Upvotes: 0
Views: 370
Reputation: 7903
var allInformationByDate = [
"1989-06-20": DayData(sales: 0, doorsKnocked: 0, milesWalked: 0.00, hoursWorked: 0.00),
"2016-06-22": DayData(sales: 2, doorsKnocked: 30, milesWalked: 2.00, hoursWorked: 3.00),
"2016-08-16": DayData(sales: 4, doorsKnocked: 30, milesWalked: 10.00, hoursWorked: 0.00)
]
override func viewDidLoad() {
super.viewDidLoad()
var avgSales:Double! = 0.0
var avgDoorsKnocked:Double! = 0.0
var avgMilesWalked:Double! = 0.0
var avgHoursWorked:Double! = 0.0
let totalDays = Double(allInformationByDate.count)
for (date, dayData) in allInformationByDate {
print("date: \(date)")
avgSales = avgSales + Double(dayData.sales)
avgDoorsKnocked = avgDoorsKnocked + Double(dayData.doorsKnocked)
avgMilesWalked = avgMilesWalked + dayData.milesWalked
avgHoursWorked = avgHoursWorked + dayData.hoursWorked
}
avgSales = avgSales/totalDays
avgDoorsKnocked = avgDoorsKnocked/totalDays
avgMilesWalked = avgMilesWalked/totalDays
avgHoursWorked = avgHoursWorked/totalDays
print("\(avgSales),\(avgDoorsKnocked),\(avgMilesWalked), \(avgHoursWorked)")
}
Upvotes: 1
Reputation: 1198
The prettiest way is to use a reduce function. You give it a starting value, and a closure that explains how to add the next item in the dictionary. In this case, our starting value would be a tuple of four elements. $0 refers to the item that is being added to, and $1 refers to the item that is added on this iteration. You can also call them $0.0 & $0.1, but I think the previous way looks nicer.
So in the closure below, $0.0, $0.1, $0.2, $0.3 are the items in the tuple, which starts as (0.0,0.0,0.0,0.0), the initial tuple.
(also note that your integer variables will get cut off and not give you the proper average. I'm going to account for that by switching them all to doubles)
let sums = allInformationByDate.reduce((0.0,0.0,0.0,0.0)) {
($0.0 + Double($1.value.sales), $0.1 + Double($1.value.doorsKnocked),
$0.2 + $1.value.milesWalked, $0.3 + $1.value.hoursWorked)
}
let n = allInformationByDate.count
let averages = (sums.0/n, sums.1/n, sums.2/n, sums.3/n) // divide each one by n. you could even give the items in the tuple names here)
edit: quick code change, forgot to specify you are adding from the value in the dictionary.
One more edit: the above assumes that those are also the variable names in the struct or class you're creating in each dictionary value.
Upvotes: 1
Reputation: 3799
Creating a function that you are passing an object of DayData into and having that function recognize that is going to be fairly difficult.
What I would recommend is either create four separate functions for each parameter, or have a number system. I will show how you could accomplish both.
This method is assuming that the members of DayData can be publicly accessed.
For just having a function for each parameter, it could look something like this:
func averageSales(dictionary: [String: DayData]) -> Double {
var total = 0
for (date, dayData) in dictionary {
total += dayData.sales
}
return = total / dictionary.count
}
Or you could have a similar method which uses a number system (1 for sales, 2 for knocked doors, etc.). It is not a very elegant solution, but you could use it if you like.
func average(dictionary: [String: DayData], parameterNumber: Int) -> Double {
var total = 0
if parameterNumber == 1 { //sales
for (date, dayData) in dictionary {
total += dayData.sales
}
return = total / dictionary.count
} else if parameterNumber == 2 { //knockedDoors
...
}
Upvotes: 0