Marshal使用块构造函数序列化Hash

时间:2014-02-16 15:01:28

标签: ruby hashmap

这是一段代码

myHash = Hash.new {|h, k| h[k] = []}
myHash[5] << 1 # example operation
Marshal.dump(myHash)

当我尝试使用任意键操作它时,我经常使用它,而且我不想明确地写这样的东西

myHash = Hash.new
myHash[5] ||= []  # initialize it first, if needed
myHash[5] << 1    # example operation
Marshal.dump(myHash)

虽然它只是一行代码差异,但对我来说使用块版本看起来更清晰。

但是,在序列化过程中会出现问题

in `dump: can't dump hash with default proc (TypeError)

有没有办法在继续使用构造函数的块形式的同时序列化它?或者,在尝试操作哈希值之前,我是否必须坚持显式检查和初始化任何值?

我会说不,因为没有真正的方法让ruby确定如果在没有传入原始proc的情况下丢失密钥时散列应该如何自动生成值。

2 个答案:

答案 0 :(得分:1)

在转储哈希值之前删除默认行为。

myHash = Hash.new {|h, k| h[k] = []}
myHash[5] << 1
myHash.default = nil
Marshal.dump(myHash)

或者,因为您似乎对保留垂直空间感兴趣:

myHash = Hash.new {|h, k| h[k] = []}
myHash[5] << 1
Marshal.dump(myHash.tap {|h| h.default = nil })

但是,这会永久更改哈希值,使其不再具有默认值。如果这困扰你,但暂时复制你的哈希的顶级不是,请抛出.dup

Marshal.dump(myHash.dup.tap {|h| h.default = nil })

现在原始哈希的默认行为保持不变。

答案 1 :(得分:1)

来自http://www.ruby-doc.org/core-2.1.0/Marshal.html第3段:

无法转储某些对象:如果要转储的对象包括绑定,过程或方法对象,类IO实例或单例对象,则会引发TypeError。

这是一个简单的例子:

class X
  def initialize a
    @a = a
  end
end
  

Marshal.dump(X.new(1))

=&GT; “\ X04 \博:\ x06X \ X06:\一个@人工智能\ X06”

  

proc = Proc.new {1}

=&GT; PROC:0x007ff992716428

  

Marshal.dump(X.new(PROC))

TypeError:没有为类Proc

定义_dump_data

使用块创建哈希时,哈希的default_proc属性为Proc:

  

h = Hash.new {1}

=&GT; {}

  

h.default_proc

=&GT; #Proc:0x007ff99506ce30 @

创建没有块的哈希时,它没有default_proc:

  

h = Hash.new

=&GT; {}

  

h.default_proc

=&GT;零