我读了一个我创建的随机文本文件
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)")
如果没有像我上面提到的上述文本文件那样排序一致性类型,则代码不起作用。我正在考虑创建一个二维数组或字典,并将一致性存储为键,并将其作为每个一致性的值,以便如果再次出现一致性,我可以将它添加到先前存储在数组/字典中的总和。我希望我有道理。我只是想知道是否有更快的方法来做到这一点。
您可以使用Array.reduce(into:)
创建一个Dictionary
,其密钥是一致性,值是具有该一致性的糖果成本的总和。然后,您只需在max(by:)
上调用Dictionary
即可找到最昂贵的一致性类型。
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
)以获得更好的可预测性和更好的性能(如果编译器知道变量是一个变量,它就可以进行优化不变)。以下结构声明与您的相同(编译器免费提供的成员初始化程序):
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")