【问题标题】:Performing array functions on an array of structs对结构数组执行数组函数
【发布时间】:2017-02-02 14:38:25
【问题描述】:

假设我有以下结构:

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

它由以下内容填充:

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))

我将如何对这些条目执行一些数组函数?

例如 - 我想弄清楚阵列中有多少独特的物种,并最终得到一个包含每个物种的新阵列。

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

我还希望能够根据这些情况进行一些计算。比如,统计所有以“Pine”为物种的条目的总董事会镜头值。

有人对我如何解决这个问题有一些建议吗?

提前谢谢你!

【问题讨论】:

  • 对于静态数据,使用数组字面量 (logInfoArray = [LogInfo(...), LogInfo(...), ... LogInfo(...)]) 比创建一个反复追加的可变数组要好得多。

标签: arrays swift function struct swift2


【解决方案1】:

要查找独特的物种,请使用map 创建species 的数组,Set 以查找独特的物种,并使用Array 将结果转换回数组:

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

要查找 Pines 的总董事会素材,请使用 filter 仅选择 Pines,然后使用 reduce 汇总 Pines 的董事会素材:

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

为了更清楚,让我们为闭包中的参数命名。

filter 的工作原理是创建一个新数组,其中仅包含原始数组中导致闭包返回 true 的那些项。在上面的示例中,过滤器创建了一个新数组,其中仅包含具有 "Pine" 作为其种类的那些项目。

reduce 通过调用数组中每个项目的闭包来工作。每次传递时,当前运行总计作为第一个参数传入(reduce(0) 中的0 是初始总计),数组中的当前项作为第二项传入。闭包返回的值是传入闭包中数组中下一项的新运行总计。

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

要查找所有项目的总板数,只需忽略仅过滤掉 Pines 的部分:

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

【讨论】:

  • 这绝对有效 - 但我无法理解 $0 和 $1 是什么,以及它实际上是如何工作的。 "$0 + $1.boardFootage" 如何知道汇总组合结果?以及这将如何转化为计算阵列中所有项目的董事会镜头?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-07-29
  • 2015-11-09
相关资源
最近更新 更多