ios - 用更少的代码快速比较两个字符串
问题描述
我有两个不同城市的数组可供选择,目标是比较这两个城市,结果将是我实现的它们之间的距离,但问题是它需要这么多行代码,我认为可能会更少比起那个来说,
到目前为止我做了什么:
结果差异定义如下:
let from_A_to_b = 423
let from_A_to_c = 1439
let from_A_to_d = 1122
...
我在 tableview 中有一个数组可供选择并传递数据:
var city = ["A","B","C","D"]
比较代码是:
if (passedCity.text == "A") && (passedCity2.text == "B") {
result.text = "\(from_A_to_b) km "
} else if (passedCity.text == "A") && (passedCity2.text == "C") {
result.text = "\(from_A_to_c) km "
} else if (passedCity.text == "A") && (passedCity2.text == "D") {
result.text = "\(from_A_to_d) km "
}
在这种情况下,我将多次重复代码,我想我可以使用 for-in 循环来完成这项工作,但我不知道这个初学者 Q 有多抱歉
解决方案
只要您的数据表是硬编码的,其中每个数据都有其磨损的属性,就没有非hacky方法可以用更少的代码来完成此操作,然后每个条目一行。
(一种“hacky”方式是生成一个表示属性名称的字符串并从字符串构造一个选择器以直接访问属性,不安全......)
在任何情况下,我都会首先创建一个包含您的城市的枚举
enum City: CaseIterable {
case cityA
case cityB
case cityC
case cityD
}
然后使用一些显示名称,例如
extension City {
var displayName: String {
switch self {
case .cityA: return "City A"
case .cityB: return "City B"
case .cityC: return "City C"
case .cityD: return "City D"
}
}
}
我会尝试在您的代码中包含 2 个属性
var selectedCityFrom: City
var selectedCityTo: City
并直接使用它们,而不是将它们转换为字符串。但是,如果您坚持使用字符串,您现在可以这样做:
extension City {
static func fromName(_ displayName: String) -> City? {
self.allCases.first(where: { $0.displayName == displayName })
}
这样做你现在解决了从你的字符串中获取一个具体的对象,你可以这样做:
guard let fromText = passedCity.text, let fromCity = City.fromName(fromText) else { return }
guard let toText = passedCity2.text, let toCity = City.fromName(toText) else { return }
let distance = City.getDistanceBetween(fromCity, toCity)
print(distance)
而现在在另一边,只有一个数据数组可能是最简单的,例如[(from: City, to: City, distance: Double)]
:
extension City {
private static let distances: [(from: City, to: City, distance: Double)] = [
(.cityA, .cityB, 423),
(.cityA, .cityC, 1439),
(.cityA, .cityD, 1122)
]
static func getDistanceBetween(_ from: City, _ to: City) -> Double? {
guard from != to else { return 0.0 } // It is a same city
guard let match = City.distances.first(where: { ($0.from == from && $0.to == to) || ($0.to == from && $0.from == to) }) else { return nil } // Data for this combination is missing
return match.distance
}
}
可能更有意义的是,您实际上将此表移动到一些外部 JSON,这些 JSON 可以与应用程序捆绑在一起,甚至可以通过远程服务器的某些 API 发送。在这种情况下,您更有可能更愿意生成类似的键cityA_cityB
并拥有一个 table [String: Double]
。例如:
{
"cityA_cityB": 423,
"cityA_cityC": 1439,
"cityA_cityD": 1122
}
那么你需要构建这样的东西:
extension City {
var JSONKey: String {
switch self {
case .cityA: return "cityA"
case .cityB: return "cityB"
case .cityC: return "cityC"
case .cityD: return "cityD"
}
}
static func getDistanceBetween(_ from: City, _ to: City, fromJSON jsonData: [String: Double]) -> Double? {
guard from != to else { return 0.0 } // It is a same city
let normalKey = [from.JSONKey, to.JSONKey].joined(separator: "_")
let reversedKey = [to.JSONKey, from.JSONKey].joined(separator: "_")
return jsonData[normalKey] ?? jsonData[reversedKey]
}
但是有很多方法可以实现同样的结果。我希望这可以帮助您找到最适合您的那个。
推荐阅读
- haskell - 不能使用 spltOn 在空格上拆分字符串
- java - Aspectj 中是否有像@annotation 标签一样的@class 标签?
- swift - 避免未终止的快速文字
- javascript - Discord.js:“如果(message.channel.name === '')”不起作用
- sql - 意外的不可恢复错误 SQL 导入向导
- java - Java - 使用执行器服务的线程
- python - Python 列表理解:如何操作文件中的文本
- javascript - Electron-fetch 将 json 作为 [object object] 返回,但网络控制台显示返回的正确 json 对象
- python - 在 Python 文档中保持别名类型简单?
- angular - 如何将路由器链接添加到 Angular 8 上的按钮单击功能?