我的代码中有一个厄运金字塔。
if places.count > 0 {
for i in 0..<places.count {
for j in 0..<places.count {
if let nameI = places[i]["name"] {
if let cityI = places[i]["city"] {
if let nameJ = places[j]["name"] {
if let cityJ = places[j]["city"] {
if let latI = places[i]["lat"] {
if let lonI = places[i]["lon"] {
if let latitudeI = Double(latI) {
if let longitudeI = Double(lonI) {
if let latJ = places[j]["lat"] {
if let lonJ = places[j]["lon"] {
if let latitudeJ = Double(latJ) {
if let longitudeJ = Double(lonJ) {
if(i != j) {
let coordinateI = CLLocation(latitude: latitudeI, longitude: longitudeI)
let coordinateJ = CLLocation(latitude: latitudeJ, longitude: longitudeJ)
let distanceInMeters = coordinateI.distance(from: coordinateJ) // result is in meters
let distanceInMiles = distanceInMeters/1609.344
var distances = [Distance]()
distances.append(Distance(
distanceInMiles: distanceInMiles,
distanceInMeters: distanceInMeters,
places: [
Place(name: nameI, city: cityI, lat: latitudeI, long: longitudeI, coordinate: coordinateI),
Place(name: nameJ, city: cityJ, lat: latitudeJ, long: longitudeJ, coordinate: coordinateJ),
]
))
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
如何避免?
是否有我应该遵循的技术或规则?
在iOS中,我们不得不用到很多if-let
。如何避免像我一样做事?
最佳答案
这是第一个近似值。如您所见,可以提取出很多重复的模式。
for (i, placeDictI) in 0..<places.enumerated() {
guard
let nameI = placeDictI["name"],
let cityI = placeDictI["city"],
let latitudeI = placeDictI["lat"].map(Double.init),
let longitudeI = placeDictI["lon"].map(Double.init),
else { continue }
let coordinateI = CLLocation(latitude: latitudeI, longitude: longitudeI)
let placeI = Place(name: nameI, city: cityI, lat: latitudeI, long: longitudeI, coordinate: coordinateI)
for (j, placeDictJ) in places.enumerated() where i != j {
guard let nameJ = placeDictI["name"],
let cityJ = placeDictI["city"],
let latitudeJ = placeDictI["lat"].map(Double.init),
let longitudeJ = placeDictI["lon"].map(Double.init)
else { continue }
let coordinateJ = CLLocation(latitude: latitudeJ, longitude: longitudeJ)
let placeJ = Place(name: nameJ, city: cityJ, lat: latitudeJ, long: longitudeJ, coordinate: coordinateJ)
let distanceInMeters = coordinateI.distance(from: coordinateJ) // result is in meters // Editor's note: REALLY? I would have thought that a variable called "distanceInMeters" would store volume in litres! Silly me!
let distanceInMiles = distanceInMeters/1609.344
var distances = [Distance]()
distances.append(Distance(
distanceInMiles: distanceInMiles,
distanceInMeters: distanceInMeters,
places: [ placeI, placeJ ]
))
}
}
以下是我应用的转换:
- 不要检查
places.count > 0
。如果它为 0,则循环不会执行任何操作。 - 对于 block 完全包含其父 block 的每个
if
语句,我将其替换为guard
。 - 用逗号合并相邻的
guard
语句。 - 将失败类型转换表示为
Optional.map(_:)
表达式,而不是guard
语句中的单独let
子句< - 将
i != j
检查更改为内部for
循环中的where
条件。 改变了这个模式:
for i in 0..<array.count { use(array[i]) use(array[i]) use(array[i]) //... }
这个模式:
for (i, element) in array.enumerated() { use(element) use(element) use(element) //... }
鉴于没有明显的重复情况,这是一个很好的暗示,即解包到 Place
的 Dictionary 属于便利初始化程序,它采用初始化 Place?
从它。更好的是,只需使用 Codable 系统,让编译器为您合成它。
关于ios - 我如何避免厄运金字塔 - iOS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53072412/