简体   繁体   English

如何进一步重构ruby哈希

[英]How to further refactor a ruby hash

I'm writing a function that takes a string and returns a corresponding model class. 我正在编写一个函数,它接受一个字符串并返回一个相应的模型类。 The old version consists of ugly case statements, and the refactored version has a less-ugly hash. 旧版本包含丑陋的case语句,重构版本的哈希值较低。 However the hash still feels repetitive to me. 然而哈希仍然感觉重复我。 Could you give me some advice? 你能给我一些建议吗?

# original function

def determine_node_label(category)
  label = 
    case category 
    when 'boundary box'
      Slide
    when 'circle', 'rectangle'
      GroupBox
    when 'text'
      Text
    when 'picture', 'pie', 'bar' , 'trend', 'star'
      Content
    else
      Content
    end
  return label 
end

# refactored function

def determine_node_label(category)
  label = {
    "boundary box" => Slide,
    "circle" => GroupBox,
    "rectangle" => GroupBox,
    "text" => Text,
    "picture" => Content,
    "pie" => Content,
    "bar" => Content,
    "trend" => Content,
    "star" => Content
  }
  label.default = Content
  return label["category"]
end

update: 更新:

I would be more interested in solutions that assume that the label.default is subject to change. 我会对假设label.default可能发生变化的解决方案更感兴趣。 My apologies for not making this clear in the code. 我很抱歉没有在代码中说清楚。

What about this? 那这个呢?

LABELS = {
  "boundary box" => Slide,
  "circle"       => GroupBox,
  "rectangle"    => GroupBox,
  "text"         => Text
} 

def determine_node_label(category)
  LABELS[category] || Content
end

If you do want the dynamic default value, you can use Hash.fetch . 如果确实需要动态默认值,可以使用Hash.fetch Also, pass the default value as the method parameter. 另外,将默认值作为方法参数传递。

LABELS = {
  "boundary box" => Slide,
  "circle"       => GroupBox,
  "rectangle"    => GroupBox,
  "text"         => Text
} 

def determine_node_label(category, default = 'Content')
  LABELS.fetch(category, default)
end

For ease of maintainability I suggest the data be maintained in the following hash. 为了便于维护,我建议将数据保存在以下哈希中。

DATA = {
  %w| boundary\ box |              => 'Slide',
  %w| circle rectangle |           => 'GroupBox',
  %w| text |                       => 'Text',
  %w| picture pie bar trend star | => 'Content'
}
  #=> {["boundary box"]=>"Slide", ["circle", "rectangle"]=>"GroupBox",
  #    ["text"]=>"Text", ["picture", "pie", "bar", "trend", "star"]=>"Content"}

Note that I made the values literals (strings) to demonstrate how this hash will be manipulated. 请注意,我创建了值literals(字符串)来演示如何操作此哈希。 In the actual application the values would not necessarily be literals. 在实际应用中,值不一定是文字。

Then provide a method to create the desired hash h from DATA and a specified default value (the latter to be returned by h[k] when h does not have a key k ). 然后提供一种从DATA和指定的默认值创建所需散列h的方法(当h没有密钥k时,后者由h[k]返回)。

def data_to_hash(data, default)
  data.each_with_object({}) { |(k,v),h| k.each { |obj| h[obj] = v } }.
       tap { |h| h.default = default }
end

This might be used as follows. 这可以如下使用。

h = data_to_hash(DATA, 'Cat')
  #=> {"boundary box"=>"Slide", "circle"=>"GroupBox",
  #    "rectangle"=>"GroupBox", "text"=>"Text", "picture"=>"Content",
  #    "pie"=>"Content", "bar"=>"Content", "trend"=>"Content",
  #    "star"=>"Content"}
h["boundary box"]
  #=> "Slide"
h["pie"]
  #=> "Content"
h["cake"]
  #=> "Cat"

To subsequently change the default you could either call data_to_hash again, with the revised default, or simply execute 要随后更改默认值,您可以使用修订后的默认值再次调用data_to_hash ,或者只是执行

h.default = "Dog"

or wrap the latter in a method. 或者将后者包装在一个方法中。

def change_default(h, new_default)
  h.default = new_default
end

change_default(h, "Dog")
  #=> "Dog"
h["pie"]
  #=> "Content"
h["cake"]
  #=> "Dog"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM