在Ruby中将哈希转换为另一个哈希

时间:2012-03-14 00:36:47

标签: ruby ruby-on-rails-3

我有一个字符串哈希

navigable_objects = { 'Dashboard' => root_path,
                      'Timesheets' => timesheets_path,
                      'Clients' => clients_path,
                      'Projects' => projects_path, 
                    }

我想将它们转换为另一个哈希,其中键也是键,但值是字符串'active'或空字符串,具体取决于当前控制器名称是否包含键。

例如,假设当前控制器名称为“ClientsController”。我得到的结果是:

{ 'Dashboard' => '',
  'Timesheets' => '',
  'Clients' => 'active',
  'Projects' => ''
}

以下是我目前的工作方式:

active = {}

navigable_objects.each do |name, path|
  active[name] = (controller.controller_name.include?(name)) ? 'active' : '')
end 

我觉得虽然这样做有效,但在Ruby中有更好的方法可以使用injecteach_with_objects吗?

4 个答案:

答案 0 :(得分:6)

更新:我发布了另一个我认为更适合您情况的答案。我将离开这个未经编辑的版本,因为它本身就有类似问题的优点。

以下是我的方式:

Hash[*navigable_objects.map{ |k,v| [k, controller.controller_name.include?(k) ? 'active' : ''] }.flatten]

您可以在哈希上运行map,该哈希获取键和值对作为块的输入。然后,您可以将数组键/值构造为数组作为输出。最后,运行Hash[*key_value_pairs.flatten]是一个很好的技巧,可以将它变回哈希。这是有效的,因为您可以将一组参数传递给Hash[]构造函数以生成哈希(Hash[1, 2, 3, 4] => { 1 => 2, 3 => 4 })。并且flatten将键值对转换为数组,*运算符将数组转换为参数列表。

这是一个冗长的版本,以防你想更清楚地看到发生了什么:

key_value_pairs = navigable_objects.map do |key, value|
    new_value = controller.controller_name.include?(k) ? 'active' : ''
    [key, new_value]
end

new_hash = Hash[*key_value_pairs.flatten]

更新:以上与ruby 1.8兼容。正如安德鲁在评论中指出的那样:

  

在1.9中,你不需要*或flatten,因为Hash []接受键值数组   对

答案 1 :(得分:4)

注意:我已经回答了,但我将此作为一个单独的答案发布,因为它对您的具体情况更好,但我的另一个答案仍然有其自身的优点。

由于您根本没有使用哈希值,可以使用each_with_object

navigable_objects.keys.each_with_object({}) { |k,h| h[k] = controller.controller_name.include?(k) ? 'active' : '' }

或者更详细地说:

new_hash = navigable_objects.keys.each_with_object({}) do |key, hash|
   hash[key] = controller.controller_name.include?(key) ? 'active' : ''
end

如果您的结果也基于这些值,那么我的其他解决方案就可以了,而这个不会。

答案 2 :(得分:1)

有许多方法可以实现这一目标。这就是我这样做的方式。

使用inject

active = navigable_objects.inject({}) do |h, obj|
  h[obj[0]] = controller.controller_name.include?(obj[0]) ? 'active' : ''
  h
end

当你在哈希上调用inject时,块会传递你注入的东西(在这种情况下是一个哈希)和一个数组,第一个元素是键,最后一个元素是值。

答案 3 :(得分:1)

从Ruby 2.0开始,有to_h:

navigable_objects.map do |name, path|
  [name, controller.controller_name.include?(name)) ? 'active' : '']
end.to_h

我认为它非常有效,但对于小哈希来说,它是一种优雅的方式。