J. Doe
J. Doe

Reputation: 13063

Use reduce to combine int from class

I looked here: Swift 3 - Reduce a collection of objects by an Int property and here: https://medium.com/@abhimuralidharan/higher-order-functions-in-swift-filter-map-reduce-flatmap-1837646a63e8 but I can not get reduce to work. Edit: Maybe because they changed the way the code compiles in swift 4 (which I am using) https://stackoverflow.com/a/46432554/7715250

This is because I get this error:

Contextual closure type '(_, Test) -> _' expects 2 arguments, but 1 was used in closure body

This is my class:

class Test {
    let amountLeftToDownload: Int
    let amountDownloaded: Int

    init(amountLeftToDownload: Int, amountDownloaded: Int) {
        self.amountLeftToDownload = amountLeftToDownload
        self.amountDownloaded = amountDownloaded
    }
}

I have an array of it (progress). I want to get the total count of downloads, which is amountLeftToDownload + amountDownloaded for each Test instance. I tried this:

let totalDownloadsToProcess = progress.reduce(0) {$0.amountLeftToDownload, $0.amountDownloaded }

I replace the comma for a +, and a few other things but it wont work.

Upvotes: 1

Views: 301

Answers (1)

vacawama
vacawama

Reputation: 154651

The closure passed to reduce takes 2 arguments: the first is the accumulator, and the second is an element from the array you are reducing. So you need to add the values from the current record to the current total:

let totalDownloadsToProcess = progress.reduce(0) { $0 + $1.amountLeftToDownload + $1.amountDownloaded }

It might be clearer if you name the inputs:

let totalDownloadsToProcess = progress.reduce(0) { totalSoFar, elem in totalSoFar + elem.amountLeftToDownload + elem.amountDownloaded }

The closure gets called for each element in the array. At each step, it returns a new value that gets passed in as totalSoFar when the next element is processed. The 0 is used as the initial value for totalSoFar when the first element is processed.

Upvotes: 2

Related Questions