0

我有一个这样的哈希:

config = {
  :assets => {
    :path => '/assets',
    :aliases => {
      '/assets/' => '/assets/index.html',
      '/assets/index.htm' => '/assets/index.html'
    }
  },
  :api => {
    :path => '/auth/api',
    :aliases => {
      '/auth/api/me' => '/auth/api/whoami'
    }
  }
}

是否可以删除重复项并config[...][:aliases]按照config[...][:path]like进行分配"#{dict_im_in()[:path]}/index.html"

4

2 回答 2

1

您正在尝试做的事情有过早优化的味道。我建议在哈希中尽可能集中使用符号作为键和值。符号的内存效率很高,查找速度也很快,因为 Ruby 只会为给定的符号创建一个内存槽,有效地做你想做的事情。

您的示例结构可以使用符号重写:

config = {
  :assets => {
    :path => :'/assets',
    :aliases => {
      :'/assets/' => :'/assets/index.html',
      :'/assets/index.htm' => :'/assets/index.html'
    }
  },
  :api => {
    :path => :'/auth/api',
    :aliases => {
      :'/auth/api/me' => :'/auth/api/whoami'
    }
  }
}

:'/assets/index.html',无论在哪里看到,总是指向同一个符号,不像字符串。

每当您需要访问期望字符串的值时,请to_s对它执行 a 。添加值时,to_sym对其执行 a 。

在幕后,您将在 Hash 中更有效地使用内存,并使用 Ruby 中最快的值查找。

现在,如果您使用哈希结构来配置您的应用程序,并且它被存储在磁盘上,您可以使用 YAML 节省一些空间,它支持其数据文件中的别名和锚点。在解析为 Ruby 对象后,它们不会在哈希内创建指针,但它们可以减小文件的大小。


编辑:

如果您需要动态定义配置,则为各种字符串的所有子部分创建变量,然后添加一个生成它的方法。以下是动态创建此类事物的基础知识:

require 'awesome_print'

def make_config(
  assets = '/assets',
  index_html = 'index.html',
  auth_api = '/auth/api'
)
  assets_index = File.join(assets, index_html)
  {
    :assets => {
      :path => assets,
      :aliases => {
        assets + '/' => assets_index,
        assets_index[0..-2] => assets_index
      }
    },
    :api => {
      :path => auth_api,
      :aliases => {
        File.join(auth_api, 'me') => File.join(auth_api, 'whoami')
      }
    }
  }
end

ap make_config()
ap make_config(
  '/new_assets',
  ['new','path','to','index.html'],
  '/auth/new_api'
)

将生成什么:

{
    :assets => {
          :path  => "/assets",
        :aliases => {
                    "/assets/"  => "/assets/index.html",
            "/assets/index.htm" => "/assets/index.html"
        }
    },
      :api => {
          :path  => "/auth/api",
        :aliases => {
            "/auth/api/me" => "/auth/api/whoami"
        }
    }
}

和:

{
    :assets => {
          :path  => "/new_assets",
        :aliases => {
                                "/new_assets/"  => "/new_assets/new/path/to/index.html",
            "/new_assets/new/path/to/index.htm" => "/new_assets/new/path/to/index.html"
        }
    },
      :api => {
          :path  => "/auth/new_api",
        :aliases => {
            "/auth/new_api/me" => "/auth/new_api/whoami"
        }
    }
}

编辑:

复制值指针的另一种方法是创建返回所需信息的 lambda 或 proc。我认为它们就像是 C 或 Perl 中的函数指针,允许我们保留范围内变量的状态,或操作传入的值。这不是一个完美的解决方案,因为会发生变量范围,但它是该框的另一个工具:

lambda1 = lambda { 'bar' }
proc2   = Proc.new { |a,b| a + b }
proc3   = Proc.new { proc2.call(1,2) }

foo = {
  :key1 => lambda1,
  :key2 => proc2,
  :key3 => proc2,
  :key4 => proc3
}

foo[:key1].object_id # => 70222460767180
foo[:key2].object_id # => 70222460365960
foo[:key3].object_id # => 70222460365960
foo[:key4].object_id # => 70222460149600

foo[:key1].call          # => "bar"
foo[:key2].call(1, 2)    # => 3
foo[:key3].call(%w[a b]) # => "ab"
foo[:key4].call          # => 3

有关 lambda 和 procs 的更多信息,请参阅“何时使用 lambda,何时使用 Proc.new? ”。

于 2013-01-08T14:25:04.683 回答
-1

这是个有趣的问题 ;)。

我认为您可以“重新打开”哈希,然后只使用变量名。

例如:

config = {
  :assets => {
    :path => '/assets',
    :aliases => {
      '/assets/' => '/assets/index.html',
      '/assets/index.htm' => '/assets/index.html'
    }
  }
}
# Then "re-open" the Hash
config[:api] = {
  :path => '/auth/api',
  :aliases => {
    '/auth/api/me' => config[:assets][:aliases]['/assets/index.htm']
  }
}

您还可以编写一个辅助方法来从该哈希中提取给定的别名。但我不确定这是否值得。

于 2013-01-08T12:43:34.720 回答