【问题标题】:Extracting currency value from a formatted string in Swift从 Swift 中的格式化字符串中提取货币值
【发布时间】:2019-11-25 06:47:45
【问题描述】:

我有以下字符串,我想从中删除货币格式并提取数值以进行操作:

"Product Price":"\u00a3314.95",

我尝试过使用以下代码:

let productvalue = model[indexPath.row].productPrice ?? ""
let prodval = productvalue.replacingOccurrences(of: "\u00a3", with: "")
let proqty = model[indexPath.row].quantity ?? ""

let totalprice = (Int(prodval)) * (Int(proqty))

但是,当我运行此代码时,我从 API 收到以下响应:

二元运算符 '*' 不能应用于两个 'Int?'操作数

【问题讨论】:

  • 理想情况下,作为最佳实践的一部分,api 应该返回不同字段中的价格和货币。
  • 作为临时规定,您可以使用子字符串从字符串中提取数字。
  • 这能回答你的问题吗? Converting String to Int with Swift

标签: swift string currency string-parsing


【解决方案1】:

问题是您使用的 init 方法返回一个可选值,因此您需要包含一个值,以防从 String 到 Int 的转换返回 nil 类似

let value = Int(someString) ?? 0

但在您的情况下,您正在处理十进制值,因此您需要转换为 Double

let totalprice = (Double(prodval) ?? 0.0) * (Double(proqty) ?? 0.0)

【讨论】:

    【解决方案2】:

    您可以使用此扩展程序来帮助您从金额中删除货币符号。

    用 $ 替换您想要的货币,例如使用 € 而不是 unicode。

    extension String {
    func removeFormatAmount() -> Double {
        let formatter = NumberFormatter()
    
        formatter.locale = Locale(identifier: "en_US")
        formatter.numberStyle = .currency
        formatter.currencySymbol = "$"
        formatter.decimalSeparator = ","
    
        return formatter.number(from: self) as Double? ?? 0
     }
    }
    

    如何使用这个扩展。

    let currencyString = "$1,000.00"
    let amount = currencyString.removeFormatAmount() // 1000.0
    

    【讨论】:

    • 这里手动你给 $ 符号,但我最后没有符号
    • 首先,你需要解码那个 Unicode 然后你需要使用这个扩展来移除 €
    【解决方案3】:

    您可以将货币字符串转换为十进制

    let str = "£300"
    
    let formatter = NumberFormatter()
    formatter.numberStyle = .currency
    formatter.currencyCode = "GBP"
    
    if let number = formatter.number(from: str) {
        let amount = number.decimalValue
        print(amount)
    }
    

    【讨论】:

      【解决方案4】:

      如果你仔细观察,字符串中的整数构造函数返回可选值。所以你有的是:

      let totalprice = {
          let a: Int? = Int(prodval)
          let b: Int? = Int(proqty)
          return a*b // Error
      }()
      

      一种快速解决方法是使用 ! 强制解包它,从而导致 let totalprice = (Int(prodval))! * (Int(proqty))! 但我不建议这样做,因为它可能会使您的应用程序崩溃。

      一个更优雅的解决方案是使用默认值:

      let totalprice = {
          let a: Int = Int(prodval) ?? 0
          let b: Int = Int(proqty) ?? 0
          return a*b
      }()
      

      但另一方面,你为什么还要在这里使用整数呢?如果价格不是整数怎么办?我建议您宁愿使用十进制数字来处理这些情况:

      let a = NSDecimalNumber(string: prodval)
      let b = NSDecimalNumber(string: proqty)
      
      let totalprice = a.multiplying(by: b)
      

      现在可以直接使用十进制数。要获得双精度值或整数值,您只需使用它的属性totalprice.doubleValuetotalprice.intValue。但也没有必要这样做。如果您需要将其转换回字符串,只需使用格式化程序:

      let formatter = NumberFormatter()
      formatter.numberStyle = .currency
      formatter.currencySymbol = "$"
      let finalOutput: String = formatter.string(from: totalprice)
      

      对此有许多可能的解决方案,如果可能的话,我会尝试使用格式化程序和十进制数字来解决所有问题。例如,在您的情况下,类似以下内容可能会起作用:

      private func generateFormatter(currencySymbol: String = "$", decimalSeparator: String = ".") -> NumberFormatter {
          let formatter = NumberFormatter()
          formatter.currencySymbol = currencySymbol
          formatter.decimalSeparator = decimalSeparator
          formatter.numberStyle = .currency
          return formatter
      }
      
      private func parseValue(_ input: String?, formatterInfo: (currencySymbol: String, decimalSeparator: String)) -> NSNumber? {
          guard let input = input else { return nil }
          let formatter = generateFormatter(currencySymbol: formatterInfo.currencySymbol, decimalSeparator: formatterInfo.decimalSeparator)
          return formatter.number(from: input)
      }
      
      private func multiplyValues(_ values: [String?], formatterInfo: (currencySymbol: String, decimalSeparator: String)) throws -> NSNumber {
          return try values.reduce(NSDecimalNumber(value: 1.0)) { result, value in
              guard let parsedValue = parseValue(value, formatterInfo: formatterInfo) else {
                  throw NSError(domain: "Parsing values", code: 400, userInfo: ["dev_message": "Could not parse a value \(value ?? "[Null value]")"])
              }
              return NSDecimalNumber(decimal: result.decimalValue).multiplying(by: NSDecimalNumber(decimal: parsedValue.decimalValue))
          }
      }
      
      let values = ["$1.2", "$1.6", "$2"]
      let result = try? multiplyValues(values, formatterInfo: ("$", "."))
      
      let parsedResult: String = {
          guard let result = try? multiplyValues(values, formatterInfo: ("$", ".")) else { return "Could not produce result" }
          return generateFormatter(currencySymbol: "$", decimalSeparator: ".").string(from: result) ?? "Could not format result"
      }()
      
      print(result ?? "No result")
      print(parsedResult)
      

      我希望代码能说明问题,您可以看到更改/注入不同格式/符号很容易。

      【讨论】:

        猜你喜欢
        • 2018-08-30
        • 2015-11-15
        • 2011-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多