首页 > 解决方案 > 用更少的代码快速比较两个字符串

问题描述

我有两个不同城市的数组可供选择,目标是比较这两个城市,结果将是我实现的它们之间的距离,但问题是它需要这么多行代码,我认为可能会更少比起那个来说,

到目前为止我做了什么:

结果差异定义如下:

   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 有多抱歉

标签: iosswift

解决方案


只要您的数据表是硬编码的,其中每个数据都有其磨损的属性,就没有非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]
    }

但是有很多方法可以实现同样的结果。我希望这可以帮助您找到最适合您的那个。


推荐阅读