Reputation: 111
I have the following struct.
struct Fruit {
var name: String
var stateCd: Int
var amt: Int
var cumulativeAvg: Int
}
var fruit = [
Fruit(name: "apple", stateCd: 0, amt: 100, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 0, amt: 200, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 1, amt: 100, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 0, amt: 300, cumulativeAvg: 0)
]
What I want is to change the value of the cumulativeAvg column to the cumulative average if stateCd is zero. If stateCd is 1, the previous average is taken without accumulating sum.
The changed values are expected to be as follows.
Fruit(name: "apple", stateCd: 0, amt: 100, cumulativeAvg: 100),
Fruit(name: "apple", stateCd: 0, amt: 200, cumulativeAvg: 150),
Fruit(name: "apple", stateCd: 1, amt: 100, cumulativeAvg: 150),
Fruit(name: "apple", stateCd: 0, amt: 300, cumulativeAvg: 200)
Upvotes: 1
Views: 117
Reputation: 11242
This would be a better and cleaner approach to your problem.
struct Fruit {
var name: String
var stateCd: Int
var amt: Double
var cumulativeAvg: Double
}
Create another structure to store the count and average for a particular fruit.
struct FruitStats {
var count: Double
var average: Double
}
Maintain a dictionary which keeps track of the count and average for each fruit.
var fruitStats: [String: FruitStats] = [:]
var fruits = [
Fruit(name: "apple", stateCd: 0, amt: 100, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 0, amt: 200, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 1, amt: 100, cumulativeAvg: 0),
Fruit(name: "apple", stateCd: 0, amt: 300, cumulativeAvg: 0),
Fruit(name: "orange", stateCd: 0, amt: 100, cumulativeAvg: 0),
Fruit(name: "orange", stateCd: 1, amt: 100, cumulativeAvg: 0),
Fruit(name: "orange", stateCd: 0, amt: 400, cumulativeAvg: 0)
]
let newFruits = fruits.map { (fruit) -> Fruit in
var newFruit = fruit
var fruitStat = fruitStats[fruit.name, default: FruitStats(count: 0, average: 0)]
if fruit.stateCd == 0 {
fruitStat.average *= fruitStat.count
fruitStat.count += 1
fruitStat.average = (fruitStat.average + fruit.amt)/fruitStat.count
}
newFruit.cumulativeAvg = fruitStat.average
fruitStats[fruit.name] = fruitStat
return newFruit
}
for fruit in newFruits {
print(fruit.name, "\t", fruit.stateCd, fruit.amt, fruit.cumulativeAvg)
}
apple 0 100.0 100.0 apple 0 200.0 150.0 apple 1 100.0 150.0 apple 0 300.0 200.0 orange 0 100.0 100.0 orange 1 100.0 100.0 orange 0 400.0 250.0
Upvotes: 1
Reputation: 13820
fruit[0].cumulativeAvg = fruit[0].amt
for (i, f) in zip(1..., fruit.dropFirst()) {
if f.stateCd == 1 {
fruit[i].cumulativeAvg = fruit[i-1].cumulativeAvg
} else {
fruit[i].cumulativeAvg = (fruit[i-1].cumulativeAvg * i + fruit[i].amt) / (i+1)
}
}
Upvotes: 0
Reputation: 7698
A simple for loop can do so
var sum = 0
var count = 0
for i in 0..<fruit.count
{
if(fruit[i].stateCd == 0)
{
count += 1
sum += fruit[i].amt
fruit[i].cumulativeAvg = sum/count
}
else if(fruit[i].stateCd == 1)
{
fruit[i].cumulativeAvg = sum/count
}
}
Upvotes: 1