ruby - 如何截断哈希中的数据以使生成的 JSON 不超过 n 个字节?

标签 ruby algorithm hash

我有一个看起来像这样的散列:

{ :a => "some string", :b => "another string", :c => "yet another string" }

我最终不想调用 to_json,但生成的 json 字符串不能长于 n 字节。

如果字符串太大,那么先截断:c。如果这还不够,:b 应该被截断。最后 :a。此外,字符串可以包含多字节字符,如德语变音符号,Ruby 版本为 1.8.7。 (变音符号首先占用 2 个字节,但作为 json,它们的长度为 5 个字节。)

我写的是一个将散列转换为_json 并检查长度的循环。如果它小于或等于 n 它被返回,否则我连接 :a + :b + :c 并缩短一半。如果新哈希太大(小),我将缩短(扩展)原始字符串的 1/4、1/8、1/16。最后我得到了 hash.as_json == n 的长度。

这一切都让人感觉非常骇人听闻,尽管所有测试都通过了检查,但我不确定它是否稳定。

有没有人对如何正确解决这个问题有好的建议?

最佳答案

怎么样:

# encoding:UTF-8

require 'rubygems'
require 'json'

def constrained_json(limit, a, b, c)
  output, size, hash  = nil, 0, { :a => a, :b => b, :c => c}
  [:c, :b, :a, :a].each do |key|
    output = hash.to_json
    size = output.bytesize
    break if size <= limit
    # on 1.9:
    # hash[key] = hash[key][0...(limit - size)]
    # on 1.8.7
    hash[key] = hash[key].unpack("U*")[0...(limit - size)].pack("U*")
  end
  raise "Size exceeds limit even after truncation" if size > limit
  output
end

38.downto(21) do |length|
  puts "# #{constrained_json(length, "Qué te", "parece", "eh?")}"
end

# {"a":"Qué te","b":"parece","c":"eh?"}
# {"a":"Qué te","b":"parece","c":"eh"}
# {"a":"Qué te","b":"parece","c":"e"}
# {"a":"Qué te","b":"parece","c":""}
# {"a":"Qué te","b":"parec","c":""}
# {"a":"Qué te","b":"pare","c":""}
# ...
# {"a":"","b":"","c":""}
# test.rb:14:in `constrained_json': Size exceeds limit even after truncation (RuntimeError)

关于ruby - 如何截断哈希中的数据以使生成的 JSON 不超过 n 个字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6777987/

相关文章:

ruby-on-rails - 完成后如何在循环内检查状态的结果?

c# - 堆栈溢出与快速排序实现

c++ - 如何在 N 个输入中获得唯一的单词

java获取唯一的服务器ID以供引用

algorithm - 没有扩散属性的散列函数/校验和是否存在?

php - 如何在不使用 OAuth 的情况下制作安全 API?

ruby - PayPal 自适应支付 - 如何获得账户 ID?

ruby - 你的 Ruby 版本是 2.0.0,但是你的 Gemfile 指定了 2.1.0

ruby-on-rails - rails : How I can get yesterday's date?

c++ - 如何使用一些关于范围的额外信息来加速二进制搜索