John Hubler
John Hubler

Reputation: 909

Performing array functions on an array of structs

Let's say that I have the following Struct:

struct LogInfo {
    var logNumber: Int
    var species: String
    var diameter: Float
    var formClass: Int
    var numLogs: Float
    var boardFootage: Double
}

And it is populated by the following:

var logInfoArray = [LogInfo]()

logInfoArray.append(LogInfo(logNumber: 1, species: "Spruce", diameter: 18.0, formClass: 78, numLogs: 1.5, boardFootage: 110.0))
logInfoArray.append(LogInfo(logNumber: 2, species: "Spruce", diameter: 17.0, formClass: 78, numLogs: 1.0, boardFootage: 90.0))
logInfoArray.append(LogInfo(logNumber: 3, species: "Pine", diameter: 18.0, formClass: 78, numLogs: 1.5, boardFootage: 89.0))
logInfoArray.append(LogInfo(logNumber: 4, species: "Pine", diameter: 21.0, formClass: 78, numLogs: 1.0, boardFootage: 120.0))
logInfoArray.append(LogInfo(logNumber: 5, species: "Pine", diameter: 19.0, formClass: 78, numLogs: 1.5, boardFootage: 200.0))
logInfoArray.append(LogInfo(logNumber: 6, species: "Oak", diameter: 22.0, formClass: 78, numLogs: 2, boardFootage: 180.0))

How would I go about performing some array functions on these entries?

For example - I would like figure out how many unique species are in the array, and end up with a new array containing each individual species.

i.e. var speciesArray = ["Spruce", "Pine", "Oak"]

I would also like to be able to then perform some calculations with those in mind. Like, tallying up the total board footage values of all entries that have "Pine" as the species.

Does anybody have some tips on how I could go about this?

Thank you in advance!

Upvotes: 0

Views: 37

Answers (1)

vacawama
vacawama

Reputation: 154603

To find the unique species, use map to create an array of the species, Set to find the unique ones, and Array to covert the result back to an array:

let unique = Array(Set(logInfoArray.map { $0.species }))
print(unique)  // ["Oak", "Pine", "Spruce"]

To find the total board footage for Pines, use filter to select just the Pines, and then use reduce to total up the board footage for the Pines:

let totalBoardFootage = logInfoArray.filter { $0.species == "Pine" }.reduce(0) { $0 + $1.boardFootage }
print(totalBoardFootage)  // 409.0

To make this clearer, let's give names to parameters in the closures.

filter works by creating a new array of only those items in the original array that cause the closure to return true. In the above example, filter creates a new array of only those items that have "Pine" as their species.

reduce works by calling the closure on each item in the array. In each pass, the current running total is passed in as the first parameter (the 0 in reduce(0) is the initial total), and the current item in the array is passed in as the second item. The value returned by the closure is the new running total that is passed into the closure for the next item in the array.

let totalBoardFootage = logInfoArray.filter { item in item.species == "Pine" }.reduce(0) { (total, item) in total + item.boardFootage }

To find the total board footage of all items, just leave out the part that filters out just Pines:

let totalBoardFootageForAllSpecies = logInfoArray.reduce(0) { (total, item) in total + item.boardFootage }

Upvotes: 1

Related Questions