swiftuiswiftui-list

Summing Multiple fields in a filtered list


I have a similar problem but I'd like to to sum up two fields instead of one (profit in the above example). let me explain:-

Here I'm defining the my array

struct DailyContractorsSummary : Identifiable, Hashable
{
    var id = UUID()
    var rigOperator: String
    var lostTime: Int
    var oPTime: Int
    var efficiency: Double
    var animate: Bool = false
}

I use the following to sum up oPTime

let filteredDailyContractorsSummary = Dictionary(grouping: Variables.dailyContractorsSummary) { element in
                                            element.rigOperator
                                        }.mapValues { recordsGroupedByRigOperator -> Int in
                                            recordsGroupedByRigOperator
                                                .map { ($0.oPTime) }
                                                .reduce(0, +)
                                        }.map { dailySummary in
                                            FilteredDailyContractorsOPTime(rigOperator: dailySummary.key, oPTime: dailySummary.value, efficiency: 0)
                                        }

I want to be able to sum up oPTime and lostTime. I can only successfully do it with oPTime or lostTime but not both together. Can you please help me? Thanks in advance

I want to be able to sum up oPTime and lostTime. I can only successfully do it with oPTime or lostTime but not both together. Can you please help me? Thanks in advance


Solution

  • The mapValues closure can return a tuple (Int, Int). The first element is the sum of opTime and the second element is the sum of lostTime.

    let filteredDailyContractorsSummary = Dictionary(
            grouping: dailyContractorsSummary, by: \.rigOperator
        )
        .mapValues { recordsGroupedByRigOperator -> (Int, Int) in
            recordsGroupedByRigOperator
                .map { ($0.oPTime, $0.lostTime) }
                .reduce((0, 0)) { ($0.0 + $1.0, $0.1 + $1.1) }
        }
    

    The expression ($0.0 + $1.0, $0.1 + $1.1) is quite hard to read, but all its doing is adding two tuples ($0 and $1) together, element by element.

    It might help to write a function like this:

    func +(lhs: (Int, Int), rhs: (Int, Int)) -> (Int, Int) {
        (lhs.0 + rhs.0, lhs.1 + rhs.1)
    }
    

    Note that you can generalise this to any tuple arity and type, but this crashes the compiler in 5.10. It works in Swift 6 though.

    func +<each T: AdditiveArithmetic>(lhs: (repeat each T), rhs: (repeat each T)) -> (repeat each T) {
        (repeat ((each lhs) + (each rhs)))
    }
    

    Then you can write .reduce((0, 0), +).

    It seems like you want to map the groups back to an array of DailyContractorsSummarys, so you can add this at the end:

    .map { key, value in
        DailyContractorsSummary(rigOperator: key, lostTime: value.0, oPTime: value.1, efficiency: 0)
    }