我在创建的随机文本文件中读取
hard toffee 10
hard toffee 20
...
chewy gum 40
soft marshmallow 20
hard toffee 30
soft marshmallow 40
我创建了一个糖果/糖果对象数组并像这样存储它:
var candyArray = [
Candy(consistency: "hard", type: "toffee", cost: 10),
...
Candy(consistency: "soft", type: "marshmellow", cost: 40)]
每个对象都可以通过其属性访问:
print((candyArray[0].type))
// prints toffeee
我想遍历数组,如果一致性很难,我想 += 用于存储硬糖成本总和的变量的成本。 我想对其他一致性做同样的事情,然后比较它们,看看总结时哪个成本最大。 任何帮助将不胜感激。 这是我到目前为止所拥有的:
struct Candy {
var consistency: String
var type: String
var cost: Double
init(consistency: String, type: String, cost: Double) {
self.consistency = consistency
self.type = type
self.cost = cost
}
}
var candyArray = [
Candy(consistency: "hard", type: "toffee", cost: 40),
Candy(consistency: "hard", type: "toffee", cost: 5),
Candy(consistency: "hard", type: "toffee", cost: 5),
Candy(consistency: "soft", type: "marshmallow", cost: 30),
Candy(consistency: "soft", type: "marshmallow", cost: 35),
Candy(consistency: "chewy", type: "gum", cost: 35)
]
print("(candyArray[0].type)")
var x = 0
var largestValue = 0.0
var tempValue = 0.0
var currentConsistency = candyArray[x].consistency
var mostExpensiveConsistency = ""
while (x < candyArray.count){
if (currentConsistency == candyArray[x].consistency) {
tempValue += candyArray[x].cost
} else if (currentConsistency != candyArray[x].consistency) {
tempValue = 0
currentConsistency = candyArray[x].consistency
}
if (tempValue > largestValue) {
largestValue = tempValue
mostExpensiveConsistency = currentConsistency
}
x+=1
}
print(" largest value: (largestValue) and most expensive consistency: (mostExpensiveConsistency)")
当一致性类型未像我提到的上述文本文件中那样排序时,代码不起作用。 我正在考虑创建一个 2d 数组或字典,并将一致性存储为每个一致性的键和总和的值,以便如果一致性再次出现,我可以将其添加到以前存储在数组/字典中的总和中。 我希望我说得有道理。我只是想知道是否有更快的方法来做到这一点。
您可以使用Array.reduce(into:)
创建一个Dictionary
,其键是一致性,值是具有该一致性的糖果成本的总和。然后,您只需在Dictionary
上调用max(by:)
即可找到最昂贵的一致性类型。
let candiesByConsistency = candyArray.reduce(into: [String:Double](), { accumulatedResults, current in
accumulatedResults[current.consistency, default: 0] += current.cost
})
let mostExpensiveConsistency = candiesByConsistency.max(by: { $0.value < $1.value })
给定示例数组的candiesByConsistency
值为
65,"硬":50,"耐嚼":35]
mostExpensiveConsistency
将是
(键"软",值 65)'
Swift 4 的字典初始值设定项可以为您完成大部分工作。
例如:
let costs = Dictionary(candyArray.map{($0.consistency,$0.cost)}, uniquingKeysWith:+)
let highest = costs.max{$0.value < $1.value} // ("soft",65)
let hardCost = costs["hard"] // 50
- 定义一个字典来保存成本摘要。
- 遍历糖果数组并汇总成本,按一致性分组。
- 将摘要缩减为单个值,始终选择成本最高的对。
let candies = [
Candy(consistency: "b", type: "b", cost: 1.5),
Candy(consistency: "a", type: "b", cost: 1.0),
Candy(consistency: "a", type: "b", cost: 2.0),
Candy(consistency: "c", type: "b", cost: 3.0),
Candy(consistency: "b", type: "b", cost: 1.0),
Candy(consistency: "c", type: "b", cost: 2.0),
]
// 1
var costSummary = [String: Double]()
// 2
candies.forEach {
costSummary[$0.consistency] = (costSummary[$0.consistency] ?? 0.0) + $0.cost
}
// 3
let mostExpensive = costSummary.reduce(("", 0.0)) { result, next in
return result.1 > next.1 ? result : next
}
这里有一个很好的管道,可以帮助你实现你的目标
let maxCost = Dictionary(grouping: candyArray, by: { $0.consistency }) // group candies by consistency
.map { ($0.key, $0.value.reduce(0) { $0 + $1.cost }) } // compute the total cost for each consistency
.sorted { $0.1 > $1.1 } // sort descending by price
.first // take the first result
结果是可选的,这将指示您尝试处理一个空的糖果数组(不太可能但可能的情况),因此您也可以处理该数组。
顺便说一句,我不禁注意到您经常使用var
,您可能希望将所有这些var
转换为只读(又名let
's) 以获得更好的可预测性和更好的性能(如果编译器知道变量是常量,它可以进行优化)。以下结构声明与您的结构声明相同(编译器免费提供的成员初始值设定项):
struct Candy {
let consistency: String
let type: String
let cost: Double
}
Swift 在集合上提供了一些不错的函数来简化这些类型的任务:map
、filter
和reduce
。
例如,您可以通过以下方式获得硬糖的总成本:
let hardCost = candyArray.filter{ $0.consistency == "hard" }.map{ $0.cost }.reduce(0, +)
这将执行以下操作:
filter
: 返回一个数组,其中仅包含与指定条件匹配的项目 (consistency == "hard"
)
map
:仅返回filter
结果中的成本数组
reduce
:通过对输入数组的所有元素执行操作(在本例中为+
)来聚合单个结果
您可以对每种类型的一致性执行相同的过程,或者编写一个扩展方法,使jut采用所需一致性的名称,例如
extension Array where Element == Candy {
func costOf(consistency: String) {
candyArray.filter{ $0.consistency == consistency }.map{ $0.cost }.reduce(0, +)
}
}
然后像这样使用它来获取每个一致性的值:
let hardCost = candyArray.costOf(consistency: "hard")
let softCost = candyArray.costOf(consistency: "soft")
let chewyCost = candyArray.costOf(consistency: "chewy")