带有对的方法的ruby哈希

时间:2012-01-20 16:42:02

标签: ruby hash

我正在使用rake任务来接收和处理数据。

数据看起来像"code:value",其中每个代码都映射到特定的操作。

例如,"0xFE:0x47"使用参数0xFE调用0x47标记对应的方法。

出于可伸缩性的考虑,我认为应该将其映射到散列并使用下面定义的方法:

tags = Hash[0xFA => taskA, 0xFB => taskB, 0xFC => taskC]

def taskA(value)
  ...
end

def taskB(value)
  ...
end

def taskC(value)
  ...
end

然后,当收到消息时,执行split并在散列上调用方法,如:

tokens = message.split(':')
tags[tokens[0]](tokens[1])

Ruby不喜欢Hash初始化。解决这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

也许你期望这些方法像在JavaScript中那样工作,在调用之前它们只是引用,但事实并非如此。最好的方法是将它们保留为符号,然后使用send方法调用它们:

# Define a mapping table between token and method to call
tags = {
  0xFA => :taskA,
  0xFB => :taskB,
  0xFC => :taskC
}

tokens = message.split(/:/)

# Call the method and pass through the value
send(tags[tokens[0]], tokens[1])

Hash[]初始化程序通常保留用于特殊情况,例如将数组转换为哈希时。在这种情况下,如果不混淆,它是多余的,因此最好省略。 { ... }具有隐式创建哈希的效果。

答案 1 :(得分:2)

定义“不喜欢”。

如果您尝试使用函数名称初始化哈希:

  1. 在定义函数之前,您将获得一个未定义的符号。
  2. 定义函数后,您只是执行该函数。
  3. 如果要将值映射到可以调用的函数,请考虑将方法定义为Procs / lambdas:

    > taskA = lambda { |value| puts "foo #{value}" }
    > h = { 0x42 => taskA }
    > h[0x42].call("bar")
    foo bar
    

    你也可以存储符号,但我更喜欢使用已知的现有工件,比如变量,所以IDE可以帮助我确保我做的事情是正确的,因为它可以知道 - 符号是任意的,没有确保它们与现有方法一致,而不是试图调用它。