Calculate the highest 2 & 3 values returned from functions

113 views Asked by At

Within a class I have 4 functions which return individual values (see code below).

I need to add 2 additional functions which calculate the total of the following:-

The total of the 2 highest numbers

The total of the 3 highest numbers

These totals will then be used in other calculations in the App.

The follow should be noted as more than 1 number could have the same value but only the relevant numbers need to be included in the total. The following are examples of what is required:

Two Highest Values

If the returns are 3, 3, 2, 1 then the return should be 6 (3 + 3)

If the returns are 3, 3, 3, 2 then the return should be 6 (3 + 3)

If the returns are 4, 3, 3, 1 then the return should be 7 (4 + 3)

Three Highest Values

If the returns are 3, 3, 2, 2 then the return should be 8 (3 + 3 + 2)

If the returns are 4, 3, 3, 3 then the return should be 10 (4 + 3 + 3)

If the returns are 3, 3, 3, 3 then the return should be 9 (3 + 3 + 3)

I have reviewed numerous searches as follows:-

  1. The ability to apply a ranking to the 4 values returned in order to use that to return the highest 2 or 3 values but cannot find any code for SwiftUI to achieve this.

  2. I found code that will apply a simple sort but nothing that then allows me to select the highest 2 or 3 values.

  3. I could use numerous nested if functions for each value to compare the value against the others and determine the highest 2 or 3 values but this would be a lot of code to achieve what is relatively a simple calculation in things like Excel.

Is there any "standard" functionality in SwiftUI to enable me to achieve his or is the long winded way of 3 above the only way it can be achieved?

Hope that makes sense?

func p1h1points(hole1par: Int16, hole1index: Int16) -> Int16 {

    let gross = p1hole1gross
    let par = hole1par
    let shot = p1h1shots(hole1index: hole1index)
    
    
    let net = Int16(gross) - Int16(shot)
    let points = par - net
    
    if p1hole1gross == 0 {
        return 0
    }
    
    if points < -1 {
        return 0
    }
    if points == -1 {
        return 1
    }
    if points == 0 {
        return 2
    }
    if points == 1 {
        return 3
    }
    if points == 2 {
        return 4
    }
    if points == 3 {
        return 5
    }
    if points == 4 {
        return 6
    }
    if points == 5 {
        return 7
    }
    if points == 6 {
        return 8
    }
    if points == 7 {
        return 9
    }
    return 0
    }



func p2h1points(hole1par: Int16, hole1index: Int16) -> Int16 {

    let gross = p2hole1gross
    let par = hole1par
    let shot = p2h1shots(hole1index: hole1index)
    
    
    let net = Int16(gross) - Int16(shot)
    let points = par - net
    
    if p2hole1gross == 0 {
        return 0
    }
    
    if points < -1 {
        return 0
    }
    if points == -1 {
        return 1
    }
    if points == 0 {
        return 2
    }
    if points == 1 {
        return 3
    }
    if points == 2 {
        return 4
    }
    if points == 3 {
        return 5
    }
    if points == 4 {
        return 6
    }
    if points == 5 {
        return 7
    }
    if points == 6 {
        return 8
    }
    if points == 7 {
        return 9
    }
    return 0
    }

func p3h1points(hole1par: Int16, hole1index: Int16) -> Int16 {

    let gross = p3hole1gross
    let par = hole1par
    let shot = p3h1shots(hole1index: hole1index)
    
    
    let net = Int16(gross) - Int16(shot)
    let points = par - net
    
    if p3hole1gross == 0 {
        return 0
    }
    
    if points < -1 {
        return 0
    }
    if points == -1 {
        return 1
    }
    if points == 0 {
        return 2
    }
    if points == 1 {
        return 3
    }
    if points == 2 {
        return 4
    }
    if points == 3 {
        return 5
    }
    if points == 4 {
        return 6
    }
    if points == 5 {
        return 7
    }
    if points == 6 {
        return 8
    }
    if points == 7 {
        return 9
    }
    return 0
    }

func p4h1points(hole1par: Int16, hole1index: Int16) -> Int16 {

    let gross = p4hole1gross
    let par = hole1par
    let shot = p4h1shots(hole1index: hole1index)
    
    
    let net = Int16(gross) - Int16(shot)
    let points = par - net
    
    if p4hole1gross == 0 {
        return 0
    }
    
    if points < -1 {
        return 0
    }
    if points == -1 {
        return 1
    }
    if points == 0 {
        return 2
    }
    if points == 1 {
        return 3
    }
    if points == 2 {
        return 4
    }
    if points == 3 {
        return 5
    }
    if points == 4 {
        return 6
    }
    if points == 5 {
        return 7
    }
    if points == 6 {
        return 8
    }
    if points == 7 {
        return 9
    }
    return 0
    }
2

There are 2 answers

0
Magnus Nordin On

Assuming that you have an array of the numbers I would do this

let highestNumbersToAdd = 2
arrayWithPoints.sort
let total = arrayWithPoints[...highestNumbersToAdd].reduce(0, +)
0
Joakim Danielson On

When implementing new functionality like this it can often be a good idea to put it in a new custom type so that this type is responsible for this new part only and the old code will not be cluttered with more responsibilities.

Also this will make it easier to change the logic or expand it if needed.

So here is a struct for calculating points that you can use from the existing code

struct PointsCalculator {
    private var playerPoints: [Int]

    init(points: [Int]) {
        playerPoints = points
    }

    var sum2Highest: Int {
        sum(for: 2)
    }

    var sum3Highest: Int {
        sum(for: 3)
    }

    private func sum(for count: Int) -> Int {
        playerPoints.sorted().suffix(count).reduce(0, +)
    }
}

This takes the points from all players as an array and works well if every player point is calculated at the same time. If on the other and points are calculated individually then the below functions might be more suitable

extension PointsCalculator {
    init() {
        playerPoints = Array(repeating: 0, count: 4)
    }

    mutating func add(_ points: Int, player: Int) {
        guard 1...4 ~= player else {
            fatalError("Player must be between 1 and 4")
        }

        playerPoints[player-1] = points
    }
}