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)
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
}
}
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
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)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.