比使用ruby gsub替换字符串更有效的方法

时间:2019-10-10 13:03:33

标签: ruby-on-rails json regex ruby string-substitution

我有一个第三方JSON提要,该提要非常大-大量数据。例如

{
   "data": [{
     "name": "ABC",
     "price": "2.50"
   },
   ...
   ]
}

我需要从价格中删除引号,因为JSON feed的消费者需要这种方式。

为此,我正在执行一个正则表达式来查找价格,然后遍历价格并使用gsub进行字符串替换。这就是我的做法:

price_strings = json.scan(/(?:"price":")(.*?)(?:")/).uniq
price_strings.each do |price|
  json.gsub!("\"#{price.reduce}\"", price.reduce)
end
json

主瓶颈似乎在每个块上。有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

如果该JSON字符串要在您的应用程序中或代码的另一个第三方依赖性(即由您的同事或模块使用)的某个时刻序列化为Hash,则建议进行协商当json已经是String时,他们可以根据需要将价格从Numeric转换为Hash,因为这样效率更高,并允许他们...

...处理边缘情况,在该情况下,如果下面我的代码中的"price": ""无法正常工作,因为它将删除"",并且将是JSON语法错误。 / strong>

但是,如果您对此没有控制权,或者正在对整个json数据进行一次性更改,那么您可以尝试以下吗?

json =
<<-eos
{
  "data": [{
    "name": "ABC",
    "price": "2.50",
    "somethingsomething": {
      "data": [{
        "name": "DEF",
        "price": "3.25", "someprop1": "hello",
        "someprop2": "world"
      }]
    },
    "somethinggggg": {
      "price": "123.45" },
    "something2222": {
      "price": 9.876, "heeeello": "world"
    }
  }]
}
eos

new_json = json.gsub /("price":.*?)"(.*?)"(.*?,|})/, '\1\2\3'

puts new_json
# =>
# {
#   "data": [{
#     "name": "ABC",
#     "price": 2.50,
#     "somethingsomething": {
#       "data": [{
#         "name": "DEF",
#         "price": 3.25, "someprop1": "hello",
#         "someprop2": "world"
#       }]
#     },
#     "somethinggggg": {
#       "price": 123.45 },
#     "something2222": {
#       "price": 9.876, "heeeello": "world"
#     }
#   }]
# }

免责声明:我不是Regexp专家。

答案 1 :(得分:2)

这真是个傻瓜差事。

JSON.parse('{ "price": 2.50 }')
> {price: 2.5}

从这个javascript示例中可以看到,使用方的解析器将截断float到它想要的任何地方。

如果要提供带格式的数字或将格式留给客户使用,请使用字符串。

实际上,使用浮点数表示货币是一个非常糟糕的主意,因为浮点数和双精度数不能准确表示我们用于货币的基数10的倍数。 JSON只有一个数字类型,可以同时表示浮点数和整数。

如果客户要使用该值进行任何类型的计算,则应使用最低货币面额的整数(欧元和美元为美分)或由消费者解释为BigDecimal等价类型的字符串。

>