I'd like to understand how the following code works:
我想了解以下代码的工作原理:
def url
@url ||= {
"basename" => self.basename,
"output_ext" => self.output_ext,
}.inject("/:basename/") { |result, token|
result.gsub(/:#{token.first}/, token.last)
}.gsub(/\/\//, "/")
end
I know what it does; somehow it returns the url corresponding to a file located o a dir on a server. So it returns strings similar to this: /path/to/my/file.html
我知道它的作用;不知何故,它返回对应于位于服务器上的目录的文件的URL。所以它返回类似于这样的字符串:/path/to/my/file.html
I understand that if @url
already has a value, it will be returned and the right ||=
will be discarded. I also understand that this begins creating a hash of two elements.
我知道如果@url已经有一个值,它将被返回,右边的|| =将被丢弃。我也明白这开始创建两个元素的哈希。
I also think I understand the last gsub; it replaces backslashes by slashes (to cope with windows servers, I guess).
我也认为我理解最后的gsub;它用斜杠替换反斜杠(以应对Windows服务器,我猜)。
What amazes me is the inject
part. I'm not able to understand it. I have used inject
before, but this one is too much for me. I don't see how this be done with an each
, since I don't understand what it does.
令我惊讶的是注射部分。我无法理解它。我之前使用过注射,但这个对我来说太过分了。我不知道每个人如何做到这一点,因为我不明白它是做什么的。
I modified the original function slightly for this question; the original comes from this jekyll file.
我为这个问题稍微修改了原来的功能;原版来自这个jekyll文件。
Cheers!
2 个解决方案
#1
2
foo.inject(bar) {|result, x| f(result,x) }
Can always be written as:
可以写成:
result = bar
foo.each {|x| result = f(result, x)}
result
So for your case, the version with each would look like this:
因此,对于您的情况,每个版本的版本如下所示:
result = "/:basename/"
{
"basename" => self.basename,
"output_ext" => self.output_ext,
}.each {|token|
result = result.gsub(/:#{token.first}/, token.last)
}
result
Meaning: for all key-value-pairs in the hash, each occurrence of the key in the "/:basename/"
is replaced with the value.
含义:对于散列中的所有键值对,“/:basename /”中每次出现的键都将替换为该值。
#2
1
Perhaps splitting the code and tweaking a little helps
也许拆分代码和调整一点帮助
options = { "basename" => self.basename, "output_ext" => self.output_ext }
options.inject("/:basename") do |result, key_and_kalue|
# Iterating over the hash yields an array of two elements, which I called key_and_value
result.gsub(":#{key_and_value[0]}", key_and_value[1])
end.gsub!(//\/\/, '/')
Basically, the inject code is iterating over all your options
and replacing for the actual value wherever it sees a ":key"
基本上,注入代码迭代所有选项并替换实际值,只要它看到“:key”
#1
2
foo.inject(bar) {|result, x| f(result,x) }
Can always be written as:
可以写成:
result = bar
foo.each {|x| result = f(result, x)}
result
So for your case, the version with each would look like this:
因此,对于您的情况,每个版本的版本如下所示:
result = "/:basename/"
{
"basename" => self.basename,
"output_ext" => self.output_ext,
}.each {|token|
result = result.gsub(/:#{token.first}/, token.last)
}
result
Meaning: for all key-value-pairs in the hash, each occurrence of the key in the "/:basename/"
is replaced with the value.
含义:对于散列中的所有键值对,“/:basename /”中每次出现的键都将替换为该值。
#2
1
Perhaps splitting the code and tweaking a little helps
也许拆分代码和调整一点帮助
options = { "basename" => self.basename, "output_ext" => self.output_ext }
options.inject("/:basename") do |result, key_and_kalue|
# Iterating over the hash yields an array of two elements, which I called key_and_value
result.gsub(":#{key_and_value[0]}", key_and_value[1])
end.gsub!(//\/\/, '/')
Basically, the inject code is iterating over all your options
and replacing for the actual value wherever it sees a ":key"
基本上,注入代码迭代所有选项并替换实际值,只要它看到“:key”