0

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!

1
  • For static data, it's much better to use an array literal (logInfoArray = [LogInfo(...), LogInfo(...), ... LogInfo(...)]) than to make a mutable array to which you repeatedly append. Commented Sep 25, 2016 at 3:07

1 Answer 1

1

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 }
Sign up to request clarification or add additional context in comments.

1 Comment

This definitely works - but I am having trouble understanding what the $0 & $1 are, and how this actually works. How does "$0 + $1.boardFootage" know to tally up the combined results? And how would this translate to tallying up the board footage of ALL items in the array?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.